├── test_pubring.gpg ├── test_secring.gpg ├── docs ├── requirements.txt ├── spelling_wordlist.txt ├── _templates │ └── page.html ├── Makefile ├── _static │ └── sidebar.js ├── conf.py └── index.rst ├── MANIFEST.in ├── pyproject.toml ├── .hgignore ├── .flake8 ├── .coveragerc ├── .gitignore ├── av-tox.ini ├── .travis.yml ├── .readthedocs.yaml ├── .github ├── ISSUE_TEMPLATE │ ├── feature_request.md │ └── bug_report.md └── workflows │ └── python-package.yml ├── .hgtags ├── appveyor.yml ├── LICENSE.txt ├── setup.cfg ├── package.json ├── release ├── tox.ini ├── messages.json └── README.rst /test_pubring.gpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vsajip/python-gnupg/HEAD/test_pubring.gpg -------------------------------------------------------------------------------- /test_secring.gpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vsajip/python-gnupg/HEAD/test_secring.gpg -------------------------------------------------------------------------------- /docs/requirements.txt: -------------------------------------------------------------------------------- 1 | sphinxcontrib-spelling==7.6.2 2 | sphinx<7 3 | sphinx-rtd-theme>=1.2.2 4 | -------------------------------------------------------------------------------- /MANIFEST.in: -------------------------------------------------------------------------------- 1 | include LICENSE.txt 2 | include README.rst 3 | include test_gnupg.py 4 | include messages.json 5 | include test_*ring.gpg 6 | 7 | -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | [build-system] 2 | requires = [ 3 | "setuptools >= 44", 4 | "wheel >= 0.29.0", 5 | ] 6 | build-backend = 'setuptools.build_meta' 7 | -------------------------------------------------------------------------------- /.hgignore: -------------------------------------------------------------------------------- 1 | (build|dist|keys|\.(tox|egg-info))/ 2 | (DETAILS|MANIFEST|random_binary_data|watcher.conf|hover.json)$ 3 | \.(pyc|log|dict-validwords|yapf)$ 4 | local.*\.(sh|cmd) 5 | docs/themes/ 6 | -------------------------------------------------------------------------------- /.flake8: -------------------------------------------------------------------------------- 1 | [flake8] 2 | max-line-length=120 3 | ignore = 4 | E731 5 | W504 6 | 7 | exclude = 8 | build 9 | .tox 10 | 11 | per-file-ignores = 12 | docs/conf.py:E265,E401,E402 13 | -------------------------------------------------------------------------------- /.coveragerc: -------------------------------------------------------------------------------- 1 | [run] 2 | branch = True 3 | omit = 4 | /home/travis/virtualenv/* 5 | /opt/python/* 6 | 7 | [report] 8 | exclude_lines = 9 | pragma: no cover 10 | raise NotImplementedError 11 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | build 2 | dist 3 | keys 4 | .tox 5 | .egg-info 6 | DETAILS 7 | MANIFEST 8 | random_binary_data 9 | __pycache__ 10 | *.pyc 11 | *.log 12 | .dict-validwords 13 | docs/themes/ 14 | docs/_build/ 15 | .idea/ 16 | .idea_modules/ 17 | *.iml 18 | *.iws 19 | *.ipr 20 | .vscode/ 21 | .settings/ 22 | .venv/ 23 | venv/ 24 | 25 | -------------------------------------------------------------------------------- /av-tox.ini: -------------------------------------------------------------------------------- 1 | [tox] 2 | #envlist = py26, py27, py34, py35, py36, pypy 3 | envlist = py26, py27, py35, py36, py37, py38, py39, pypy 4 | isolated_build = True 5 | 6 | [testenv] 7 | commands = {envpython} test_gnupg.py 8 | 9 | # 10 | # AppVeyor has a rogue copy of gpg2.2.19 lying around, which messes things up unless 11 | # the gpg binary we want is specified with the correct absolute path. The location 12 | # below is the default location of the executable installed by "choco install gnupg". 13 | # 14 | setenv = 15 | NO_EXTERNAL_TESTS=1 16 | GPGBINARY=C:\Program Files (x86)\GnuPG\bin\gpg.exe 17 | 18 | deps = 19 | 20 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | dist: xenial 2 | language: python 3 | sudo: false 4 | python: 5 | # - "2.6" removed because tests aren't 2.6-compatible 6 | - "2.7" 7 | # - "3.2" removed because Coveralls/coverage 4.0 fails on 3.2 8 | # - "3.3" removed because fails on Travis with Xenial 9 | - "3.4" 10 | - "3.5" 11 | - "3.6" 12 | - "3.7" 13 | - "3.8" 14 | - "pypy2.7-6.0" 15 | - "pypy3.5-6.0" 16 | install: 17 | - pip install coveralls 18 | script: 19 | - "NO_EXTERNAL_TESTS=1 python test_gnupg.py --no-doctests" 20 | - "NO_EXTERNAL_TESTS=1 coverage run test_gnupg.py --no-doctests" 21 | after_success: coveralls 22 | -------------------------------------------------------------------------------- /.readthedocs.yaml: -------------------------------------------------------------------------------- 1 | # .readthedocs.yaml 2 | # Read the Docs configuration file 3 | # See https://docs.readthedocs.io/en/stable/config-file/v2.html for details 4 | 5 | # Required 6 | version: 2 7 | 8 | # Set the version of Python and other tools you might need 9 | build: 10 | os: ubuntu-22.04 11 | tools: 12 | python: "3.11" 13 | 14 | # Build documentation in the docs/ directory with Sphinx 15 | sphinx: 16 | configuration: docs/conf.py 17 | 18 | # We recommend specifying your dependencies to enable reproducible builds: 19 | # https://docs.readthedocs.io/en/stable/guides/reproducible-builds.html 20 | python: 21 | install: 22 | - requirements: docs/requirements.txt 23 | 24 | -------------------------------------------------------------------------------- /docs/spelling_wordlist.txt: -------------------------------------------------------------------------------- 1 | Cunnane 2 | Folkinshteyn 3 | Dmitry 4 | Gladkov 5 | Abdul 6 | Karim 7 | Yann 8 | Leboulanger 9 | Kirill 10 | Yakovenko 11 | Leftwich 12 | Michal 13 | Niklas 14 | Noël 15 | Jannis 16 | Leidel 17 | Venzen 18 | Khaosan 19 | Pörner 20 | Kévin 21 | dprovins 22 | ernest 23 | eyepulp 24 | hysterix 25 | slackin 26 | natureshadow 27 | gpgbinary 28 | gpg 29 | env 30 | Kuchling 31 | Traugott 32 | Wayback 33 | gnupg 34 | etc 35 | latin 36 | Autogenerated 37 | Bloggs 38 | Gamal 39 | pinentry 40 | keyid 41 | keyids 42 | Jython 43 | algo 44 | ownertrust 45 | uid 46 | sig 47 | Keygrip 48 | keygrip 49 | truthy 50 | libgpg 51 | th 52 | armor 53 | clearsign 54 | armored 55 | args 56 | popups 57 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Is your feature request related to a problem? Please describe.** 11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 12 | 13 | **Describe the solution you'd like** 14 | A clear and concise description of what you want to happen. 15 | 16 | **Describe alternatives you've considered** 17 | A clear and concise description of any alternative solutions or features you've considered. 18 | 19 | **Additional context** 20 | Add any other context or screenshots about the feature request here. 21 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve this library. 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Describe the bug** 11 | A clear and concise description of what the bug is. 12 | 13 | **To Reproduce** 14 | Steps to reproduce the behavior: 15 | 1. Go to '...' 16 | 2. Click on '....' 17 | 3. Scroll down to '....' 18 | 4. See error 19 | 20 | **Expected behavior** 21 | A clear and concise description of what you expected to happen. 22 | 23 | **Screenshots** 24 | If applicable, add screenshots to help explain your problem. 25 | 26 | **Environment** 27 | - OS, including version 28 | - Version of this library 29 | - Version of GnuPG 30 | 31 | **Additional information** 32 | Add any other information about the problem here. 33 | -------------------------------------------------------------------------------- /.hgtags: -------------------------------------------------------------------------------- 1 | afbe4e74cfc7fb79dde344499e8934c88874ef85 0.3.6 2 | 1979c07150aa6c7cb16b7f70db71f1b973153b93 0.3.7 3 | 7a54f558eb05e2b0ff25b51f430255d92312705c 0.3.8 4 | 1ab8db449e5b2b28b2d1f4c96677dd31050d296e 0.3.9 5 | d18b8320539fc43cf406e829080d9fb72388f7ce 0.4.0 6 | 1fe9f4c3d9b3a7672a43beb8ee08ac3e8234710d 0.4.1 7 | 20a9a5727c11ea07188f99377c67d1bd937f4d7e 0.4.2 8 | e0f2692d6539aca706b63dba22d900d2c70d59f8 0.4.3 9 | c2dc6e154027ab8fc13eba8a440ea43568c37d8b 0.4.4 10 | 5cedc567072cead1415b24b7aa1ee74901c3f66f 0.4.4.1 11 | 79af87708a2338d1ec58b5ff32747a6dc32e5147 0.4.5 12 | 5eae1f2c1034f1eb3e5b29dece3a7006cd687733 0.4.6 13 | 2eae4d96f406b9f09b274b6a2457b0a87a1a894e 0.4.7 14 | 0a57c41eb34b01878fa6ac00a6f1afb2e1c4f6be 0.4.8 15 | 9e58092577ebf033bd8b95dc50905e518ff4a7ea 0.4.9 16 | 129c8fa7451a75c71f5e2fd54686896b266fefc8 0.5.0 17 | 1f1265fd99f1dda764dfa5ba3b4f34093203eaf5 0.5.1 18 | f7d1effbb6e19cc233a139510c04f0f3aad83dd7 0.5.2 19 | b0327e6c3ce295d2f5780af98e7aec0cf1862091 0.5.3 20 | 3efac76918850def676c20aa4bddb6e132adf1b6 0.5.4 21 | 1b77f5b12ad72096eb71fd94b2f767ffc565d3eb 0.5.5 22 | -------------------------------------------------------------------------------- /docs/_templates/page.html: -------------------------------------------------------------------------------- 1 | {% extends "!page.html" %} 2 | 3 | {% block body %} 4 | {{ super() }} 5 | 18 | 19 | {% endblock %} 20 | {% block footer %} 21 | {{ super() }} 22 | 30 | {% endblock %} 31 | 32 | -------------------------------------------------------------------------------- /appveyor.yml: -------------------------------------------------------------------------------- 1 | version: 1.0.{build} 2 | image: 3 | - Visual Studio 2017 4 | - ubuntu1804 5 | - macos 6 | - macos-mojave 7 | environment: 8 | NO_EXTERNAL_TESTS: 1 9 | matrix: 10 | - TOXENV: py27 11 | # - TOXENV: py34 12 | - TOXENV: py35 13 | - TOXENV: py36 14 | - TOXENV: py37 15 | - TOXENV: py38 16 | # - TOXENV: py39 17 | 18 | for: 19 | - 20 | matrix: 21 | only: 22 | - image: Visual Studio 2017 23 | 24 | install: 25 | - ps: | 26 | $path = [Environment]::GetEnvironmentVariable("path", "machine") 27 | $origPath = $path 28 | $newPath = ($path.Split(';') | Where-Object { $_ -eq 'C:\ProgramData\chocolatey\bin' }) -join ';' 29 | [Environment]::SetEnvironmentVariable("path", $newPath, "machine") 30 | refreshenv 31 | appveyor-retry choco install gnupg 32 | $newPath = "C:\Program Files (x86)\GnuPG\bin;" + $origPath 33 | [Environment]::SetEnvironmentVariable("path", $newPath, "machine") 34 | refreshenv 35 | Write-Host $newPath 36 | cmd /r "C:\Program Files (x86)\GnuPG\bin\gpg.exe" --version 37 | 38 | - cmd: pip install tox 39 | 40 | install: 41 | - cmd: pip install tox 42 | build: off 43 | test_script: 44 | - cmd: tox -c av-tox.ini 45 | on_failure: 46 | - cmd: type test_gnupg.log 47 | 48 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2008-2022 by Vinay Sajip. 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | * Redistributions of source code must retain the above copyright notice, 8 | this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above copyright notice, 10 | this list of conditions and the following disclaimer in the documentation 11 | and/or other materials provided with the distribution. 12 | * The name(s) of the copyright holder(s) may not be used to endorse or 13 | promote products derived from this software without specific prior 14 | written permission. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) "AS IS" AND ANY EXPRESS OR 17 | IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 18 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 19 | EVENT SHALL THE COPYRIGHT HOLDER(S) BE LIABLE FOR ANY DIRECT, INDIRECT, 20 | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 21 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 22 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 23 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 24 | OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 25 | ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | 27 | -------------------------------------------------------------------------------- /.github/workflows/python-package.yml: -------------------------------------------------------------------------------- 1 | name: Tests 2 | 3 | on: 4 | push: 5 | branches: [ master ] 6 | paths-ignore: 7 | - 'LICENSE.*' 8 | - 'README.*' 9 | - '.github/ISSUE-TEMPLATE/**' 10 | - 'docs/**' 11 | - '.hgignore' 12 | - '.gitignore' 13 | 14 | pull_request: 15 | branches: [ master ] 16 | paths-ignore: 17 | - 'LICENSE.*' 18 | - 'README.*' 19 | - '.github/ISSUE-TEMPLATE/**' 20 | - 'docs/**' 21 | - '.hgignore' 22 | - '.gitignore' 23 | 24 | schedule: # at 03:07 on day-of-month 7 25 | - cron: '7 3 7 * *' 26 | 27 | jobs: 28 | build: 29 | runs-on: ${{ matrix.os }} 30 | strategy: 31 | fail-fast: false 32 | matrix: 33 | os: [ubuntu-latest, macos-latest, windows-latest] 34 | python-version: ['3.8', '3.9', '3.10', '3.11', '3.12', '3.13', '3.13t', 'pypy-3.9'] 35 | 36 | steps: 37 | - uses: actions/checkout@v4 38 | - name: Set up Python ${{ matrix.python-version }} 39 | uses: actions/setup-python@v5 40 | with: 41 | python-version: ${{ matrix.python-version }} 42 | - name: Install Windows-only dependencies 43 | run: | 44 | $env:PATH = "C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Windows\System32\WindowsPowerShell\v1.0\;C:\ProgramData\chocolatey\bin" 45 | [Environment]::SetEnvironmentVariable("Path", $env:PATH, "Machine") 46 | choco install gnupg 47 | echo "C:\Program Files (x86)\GnuPG\bin" >> $env:GITHUB_PATH 48 | if: ${{ matrix.os == 'windows-latest' }} 49 | - name: Test with unittest 50 | run: | 51 | gpg --version 52 | python test_gnupg.py -v 53 | env: 54 | NO_EXTERNAL_TESTS: 1 55 | - name: Report failure info 56 | if: ${{ failure() }} 57 | run: | 58 | cat test_gnupg.log 59 | - name: Test with coverage 60 | run: | 61 | pip install coverage 62 | coverage run --branch test_gnupg.py 63 | coverage xml 64 | env: 65 | NO_EXTERNAL_TESTS: 1 66 | - name: Upload coverage to Codecov 67 | uses: codecov/codecov-action@v4 68 | with: 69 | flags: unittests 70 | files: coverage.xml 71 | -------------------------------------------------------------------------------- /setup.cfg: -------------------------------------------------------------------------------- 1 | [metadata] 2 | name = python-gnupg 3 | version = attr: gnupg.__version__ 4 | description = A wrapper for the Gnu Privacy Guard (GPG or GnuPG) 5 | long_description = 6 | This module allows easy access to GnuPG's key management, encryption and signature 7 | functionality from Python programs. It is intended for use with Python 2.4 or 8 | greater. 9 | 10 | Releases are normally signed using a GnuPG key with the user id 11 | vinay_sajip@yahoo.co.uk and the following fingerprint: 12 | 13 | CA74 9061 914E AC13 8E66 EADB 9147 B477 339A 9B86 14 | 15 | As PyPI no longer shows signatures, you should be able to download release archives 16 | and signatures from 17 | 18 | https://github.com/vsajip/python-gnupg/releases/ 19 | 20 | The archives should be the same as those uploaded to PyPI. 21 | 22 | url = https://github.com/vsajip/python-gnupg 23 | author = Vinay Sajip 24 | author_email = vinay_sajip@yahoo.co.uk 25 | maintainer = Vinay Sajip 26 | maintainer_email = vinay_sajip@yahoo.co.uk 27 | license = BSD 28 | license_files = LICENSE.txt 29 | platforms = any 30 | classifiers = 31 | Development Status :: 5 - Production/Stable 32 | Intended Audience :: Developers 33 | License :: OSI Approved :: BSD License 34 | Programming Language :: Python 35 | Programming Language :: Python :: 2 36 | Programming Language :: Python :: 3 37 | Programming Language :: Python :: 2.7 38 | Programming Language :: Python :: 3.6 39 | Programming Language :: Python :: 3.7 40 | Programming Language :: Python :: 3.8 41 | Programming Language :: Python :: 3.9 42 | Programming Language :: Python :: 3.10 43 | Programming Language :: Python :: 3.11 44 | Programming Language :: Python :: 3.12 45 | Programming Language :: Python :: 3.13 46 | Operating System :: OS Independent 47 | Topic :: Software Development :: Libraries :: Python Modules 48 | project_urls = 49 | Documentation = https://gnupg.readthedocs.io/ 50 | Source = https://github.com/vsajip/python-gnupg 51 | Tracker = https://github.com/vsajip/python-gnupg/issues 52 | keywords = GnuPG,cryptography,encryption,decryption,signing,verification 53 | 54 | [options] 55 | py_modules = gnupg 56 | 57 | [bdist_wheel] 58 | universal = 1 59 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "index-metadata": { 3 | "extensions": { 4 | "python.details": { 5 | "classifiers": [ 6 | "Development Status :: 5 - Production/Stable", 7 | "Intended Audience :: Developers", 8 | "License :: OSI Approved :: BSD License", 9 | "Programming Language :: Python", 10 | "Programming Language :: Python :: 2", 11 | "Programming Language :: Python :: 3", 12 | "Programming Language :: Python :: 2.4", 13 | "Programming Language :: Python :: 2.5", 14 | "Programming Language :: Python :: 2.6", 15 | "Programming Language :: Python :: 2.7", 16 | "Programming Language :: Python :: 3.2", 17 | "Programming Language :: Python :: 3.3", 18 | "Programming Language :: Python :: 3.4", 19 | "Programming Language :: Python :: 3.5", 20 | "Programming Language :: Python :: 3.6", 21 | "Programming Language :: Python :: 3.7", 22 | "Operating System :: OS Independent", 23 | "Topic :: Software Development :: Libraries :: Python Modules" 24 | ], 25 | "license": "Copyright (C) 2008-2019 by Vinay Sajip. All Rights Reserved. See LICENSE.txt for license." 26 | }, 27 | "python.project": { 28 | "contacts": [ 29 | { 30 | "email": "vinay_sajip@red-dove.com", 31 | "name": "Vinay Sajip", 32 | "role": "author" 33 | }, 34 | { 35 | "email": "vinay_sajip@red-dove.com", 36 | "name": "Vinay Sajip", 37 | "role": "maintainer" 38 | } 39 | ], 40 | "project_urls": { 41 | "Home": "http://packages.python.org/python-gnupg/index.html" 42 | } 43 | } 44 | }, 45 | "metadata_version": "2.0", 46 | "name": "python-gnupg", 47 | "python.exports": { 48 | "modules": [ 49 | "gnupg" 50 | ] 51 | }, 52 | "source_url": "https://pypi.io/packages/source/p/python-gnupg/python-gnupg-0.4.5.tar.gz", 53 | "summary": "A wrapper for the Gnu Privacy Guard (GPG or GnuPG)", 54 | "version": "0.4.5" 55 | }, 56 | "metadata": { 57 | "description": "This module allows easy access to GnuPG's key management, encryption and signature functionality from Python programs. It is intended for use with Python 2.4 or greater.", 58 | "name": "python-gnupg", 59 | "platform": "No particular restrictions", 60 | "version": "0.4.5" 61 | }, 62 | "source": { 63 | "modules": [ 64 | "gnupg" 65 | ] 66 | }, 67 | "version": 1 68 | } 69 | -------------------------------------------------------------------------------- /release: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | # 4 | # Copyright (C) 2023 Red Dove Consultants Limited 5 | # 6 | import argparse 7 | import glob 8 | import logging 9 | import os 10 | import re 11 | import subprocess 12 | import sys 13 | 14 | DEBUGGING = 'PY_DEBUG' in os.environ 15 | 16 | logger = logging.getLogger(__name__) 17 | 18 | 19 | def main(): 20 | fn = os.path.basename(__file__) 21 | fn = os.path.splitext(fn)[0] 22 | lfn = os.path.expanduser('~/logs/%s.log' % fn) 23 | if os.path.isdir(os.path.dirname(lfn)): 24 | logging.basicConfig(level=logging.DEBUG, filename=lfn, filemode='w', 25 | format='%(message)s') 26 | adhf = argparse.ArgumentDefaultsHelpFormatter 27 | ap = argparse.ArgumentParser(formatter_class=adhf, prog=fn) 28 | aa = ap.add_argument 29 | aa('-b', '--build', default=False, action='store_true', help='Force a rebuild') 30 | aa('-u', '--upload', default=False, action='store_true', help='Upload to PyPI') 31 | options = ap.parse_args() 32 | with open('gnupg.py') as f: 33 | data = f.read() 34 | m = re.search(r"__version__\s*=\s*'(.*)'", data) 35 | assert m 36 | ver = m.groups()[0] 37 | sigs = list(glob.glob(f'dist/*{ver}*.asc')) 38 | # import pdb; pdb.set_trace() 39 | if sigs and not options.build: 40 | print(f'Signatures found: {", ".join(sigs)}') 41 | else: 42 | if not sigs: 43 | print('Signatures not found ...') 44 | files = [fn for fn in glob.glob(f'dist/*{ver}*') if not fn.endswith('.asc')] 45 | if files and not options.build: 46 | print(f'Archives found: {", ".join(files)}') 47 | else: 48 | if not files: 49 | print('Archives not found ...') 50 | subprocess.check_call(['pybuild']) 51 | files = [fn for fn in glob.glob(f'dist/*{ver}*') if not fn.endswith('.asc')] 52 | for fn in files: 53 | sfn = f'{fn}.asc' 54 | if os.path.exists(sfn): 55 | os.remove(sfn) 56 | cmd = ['gpg2', '-abs', fn] 57 | p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE) 58 | p.communicate() 59 | assert p.returncode == 0 60 | if options.upload: 61 | cmd = ['twine', 'upload', '-r', 'python-gnupg'] 62 | cmd.extend(files) 63 | subprocess.check_call(cmd) 64 | 65 | 66 | if __name__ == '__main__': 67 | try: 68 | rc = main() 69 | except KeyboardInterrupt: 70 | rc = 2 71 | except Exception as e: 72 | if DEBUGGING: 73 | s = ' %s:' % type(e).__name__ 74 | else: 75 | s = '' 76 | sys.stderr.write('Failed:%s %s\n' % (s, e)) 77 | if DEBUGGING: import traceback; traceback.print_exc() 78 | rc = 1 79 | sys.exit(rc) 80 | -------------------------------------------------------------------------------- /tox.ini: -------------------------------------------------------------------------------- 1 | # tox (https://tox.readthedocs.io/) is a tool for running tests 2 | # in multiple virtualenvs. This configuration file will run the 3 | # test suite on all supported python versions. To use it, "pip install tox" 4 | # and then run "tox" from this directory. 5 | 6 | [tox] 7 | #envlist = py26, py27, py34, py35, py36, pypy 8 | envlist = py27, py38, py39, py310, py311, py312, py313, pypy, 9 | py27gpg2, py38gpg2, py39gpg2, py310gpg2, py311gpg2, py312gpg2, 10 | py313gpg2, pypygpg2 11 | isolated_build = True 12 | 13 | [testenv] 14 | commands = {envpython} test_gnupg.py 15 | 16 | setenv = 17 | NO_EXTERNAL_TESTS=1 18 | 19 | passenv = 20 | HOME 21 | ENABLE_TOFU 22 | STATIC_TEST_HOMEDIR 23 | 24 | deps = 25 | 26 | 27 | [testenv:py27gpg2] 28 | envdir = {toxinidir}/.tox/py27 29 | basepython = python2.7 30 | setenv = 31 | LD_LIBRARY_PATH=/home/vinay/tmp/lib 32 | GPGBINARY=gpg2 33 | NO_EXTERNAL_TESTS=1 34 | 35 | passenv = 36 | HOME 37 | ENABLE_TOFU 38 | 39 | [testenv:py36gpg2] 40 | envdir = {toxinidir}/.tox/py36 41 | basepython = python3.6 42 | setenv = 43 | LD_LIBRARY_PATH=/home/vinay/tmp/lib 44 | GPGBINARY=gpg2 45 | NO_EXTERNAL_TESTS=1 46 | 47 | passenv = 48 | HOME 49 | ENABLE_TOFU 50 | 51 | [testenv:py37gpg2] 52 | envdir = {toxinidir}/.tox/py37 53 | basepython = python3.7 54 | setenv = 55 | LD_LIBRARY_PATH=/home/vinay/tmp/lib 56 | GPGBINARY=gpg2 57 | NO_EXTERNAL_TESTS=1 58 | 59 | passenv = 60 | HOME 61 | ENABLE_TOFU 62 | 63 | [testenv:py38gpg2] 64 | envdir = {toxinidir}/.tox/py38 65 | basepython = python3.8 66 | setenv = 67 | LD_LIBRARY_PATH=/home/vinay/tmp/lib 68 | GPGBINARY=gpg2 69 | NO_EXTERNAL_TESTS=1 70 | 71 | passenv = 72 | HOME 73 | ENABLE_TOFU 74 | 75 | [testenv:py39gpg2] 76 | envdir = {toxinidir}/.tox/py39 77 | basepython = python3.9 78 | setenv = 79 | LD_LIBRARY_PATH=/home/vinay/tmp/lib 80 | GPGBINARY=gpg2 81 | NO_EXTERNAL_TESTS=1 82 | 83 | passenv = 84 | HOME 85 | ENABLE_TOFU 86 | 87 | [testenv:py310gpg2] 88 | envdir = {toxinidir}/.tox/py310 89 | basepython = python3.10 90 | setenv = 91 | LD_LIBRARY_PATH=/home/vinay/tmp/lib 92 | GPGBINARY=gpg2 93 | NO_EXTERNAL_TESTS=1 94 | 95 | passenv = 96 | HOME 97 | ENABLE_TOFU 98 | 99 | [testenv:py311gpg2] 100 | envdir = {toxinidir}/.tox/py311 101 | basepython = python3.11 102 | setenv = 103 | LD_LIBRARY_PATH=/home/vinay/tmp/lib 104 | GPGBINARY=gpg2 105 | NO_EXTERNAL_TESTS=1 106 | 107 | passenv = 108 | HOME 109 | ENABLE_TOFU 110 | 111 | [testenv:py312gpg2] 112 | envdir = {toxinidir}/.tox/py312 113 | basepython = python3.12 114 | setenv = 115 | LD_LIBRARY_PATH=/home/vinay/tmp/lib 116 | GPGBINARY=gpg2 117 | NO_EXTERNAL_TESTS=1 118 | 119 | [testenv:py313gpg2] 120 | envdir = {toxinidir}/.tox/py313 121 | basepython = python3.13 122 | setenv = 123 | LD_LIBRARY_PATH=/home/vinay/tmp/lib 124 | GPGBINARY=gpg2 125 | NO_EXTERNAL_TESTS=1 126 | 127 | passenv = 128 | HOME 129 | ENABLE_TOFU 130 | 131 | [testenv:pypygpg2] 132 | envdir = {toxinidir}/.tox/pypy 133 | basepython = pypy 134 | setenv = 135 | LD_LIBRARY_PATH=/home/vinay/tmp/lib 136 | GPGBINARY=gpg2 137 | NO_EXTERNAL_TESTS=1 138 | 139 | passenv = 140 | HOME 141 | ENABLE_TOFU 142 | -------------------------------------------------------------------------------- /docs/Makefile: -------------------------------------------------------------------------------- 1 | # Makefile for Sphinx documentation 2 | # 3 | 4 | # You can set these variables from the command line. 5 | SPHINXOPTS = 6 | SPHINXBUILD = sphinx-build 7 | PAPER = 8 | BUILDDIR = _build 9 | 10 | # Internal variables. 11 | PAPEROPT_a4 = -D latex_paper_size=a4 12 | PAPEROPT_letter = -D latex_paper_size=letter 13 | ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . 14 | 15 | .PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest remote apidocs 16 | 17 | help: 18 | @echo "Please use \`make ' where is one of" 19 | @echo " html to make standalone HTML files" 20 | @echo " dirhtml to make HTML files named index.html in directories" 21 | @echo " singlehtml to make a single large HTML file" 22 | @echo " pickle to make pickle files" 23 | @echo " json to make JSON files" 24 | @echo " htmlhelp to make HTML files and a HTML help project" 25 | @echo " qthelp to make HTML files and a qthelp project" 26 | @echo " devhelp to make HTML files and a Devhelp project" 27 | @echo " epub to make an epub" 28 | @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" 29 | @echo " latexpdf to make LaTeX files and run them through pdflatex" 30 | @echo " text to make text files" 31 | @echo " man to make manual pages" 32 | @echo " changes to make an overview of all changed/added/deprecated items" 33 | @echo " linkcheck to check all external links for integrity" 34 | @echo " doctest to run all doctests embedded in the documentation (if enabled)" 35 | 36 | clean: 37 | -rm -rf $(BUILDDIR)/* 38 | 39 | html: 40 | $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html 41 | @echo 42 | @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." 43 | 44 | apidocs: 45 | docfrag --libs .. gnupg -f hovertip > hover.json 46 | 47 | remote: 48 | rsync -avz $(BUILDDIR)/html/* vopal:~/apps/rdc_docs/python-gnupg 49 | 50 | spelling: 51 | $(SPHINXBUILD) -b spelling $(ALLSPHINXOPTS) $(BUILDDIR) 52 | 53 | dirhtml: 54 | $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml 55 | @echo 56 | @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml." 57 | 58 | singlehtml: 59 | $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml 60 | @echo 61 | @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml." 62 | 63 | pickle: 64 | $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle 65 | @echo 66 | @echo "Build finished; now you can process the pickle files." 67 | 68 | json: 69 | $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json 70 | @echo 71 | @echo "Build finished; now you can process the JSON files." 72 | 73 | htmlhelp: 74 | $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp 75 | @echo 76 | @echo "Build finished; now you can run HTML Help Workshop with the" \ 77 | ".hhp project file in $(BUILDDIR)/htmlhelp." 78 | 79 | qthelp: 80 | $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp 81 | @echo 82 | @echo "Build finished; now you can run "qcollectiongenerator" with the" \ 83 | ".qhcp project file in $(BUILDDIR)/qthelp, like this:" 84 | @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/Distlib.qhcp" 85 | @echo "To view the help file:" 86 | @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/Distlib.qhc" 87 | 88 | devhelp: 89 | $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp 90 | @echo 91 | @echo "Build finished." 92 | @echo "To view the help file:" 93 | @echo "# mkdir -p $$HOME/.local/share/devhelp/Distlib" 94 | @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/Distlib" 95 | @echo "# devhelp" 96 | 97 | epub: 98 | $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub 99 | @echo 100 | @echo "Build finished. The epub file is in $(BUILDDIR)/epub." 101 | 102 | latex: 103 | $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex 104 | @echo 105 | @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex." 106 | @echo "Run \`make' in that directory to run these through (pdf)latex" \ 107 | "(use \`make latexpdf' here to do that automatically)." 108 | 109 | latexpdf: 110 | $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex 111 | @echo "Running LaTeX files through pdflatex..." 112 | make -C $(BUILDDIR)/latex all-pdf 113 | @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." 114 | 115 | text: 116 | $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text 117 | @echo 118 | @echo "Build finished. The text files are in $(BUILDDIR)/text." 119 | 120 | man: 121 | $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man 122 | @echo 123 | @echo "Build finished. The manual pages are in $(BUILDDIR)/man." 124 | 125 | changes: 126 | $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes 127 | @echo 128 | @echo "The overview file is in $(BUILDDIR)/changes." 129 | 130 | linkcheck: 131 | $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck 132 | @echo 133 | @echo "Link check complete; look for any errors in the above output " \ 134 | "or in $(BUILDDIR)/linkcheck/output.txt." 135 | 136 | doctest: 137 | $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest 138 | @echo "Testing of doctests in the sources finished, look at the " \ 139 | "results in $(BUILDDIR)/doctest/output.txt." 140 | -------------------------------------------------------------------------------- /docs/_static/sidebar.js: -------------------------------------------------------------------------------- 1 | /* 2 | * sidebar.js 3 | * ~~~~~~~~~~ 4 | * 5 | * This script makes the Sphinx sidebar collapsible. 6 | * 7 | * .sphinxsidebar contains .sphinxsidebarwrapper. This script adds in 8 | * .sphixsidebar, after .sphinxsidebarwrapper, the #sidebarbutton used to 9 | * collapse and expand the sidebar. 10 | * 11 | * When the sidebar is collapsed the .sphinxsidebarwrapper is hidden and the 12 | * width of the sidebar and the margin-left of the document are decreased. 13 | * When the sidebar is expanded the opposite happens. This script saves a 14 | * per-browser/per-session cookie used to remember the position of the sidebar 15 | * among the pages. Once the browser is closed the cookie is deleted and the 16 | * position reset to the default (expanded). 17 | * 18 | * :copyright: Copyright 2007-2011 by the Sphinx team, see AUTHORS. 19 | * :license: BSD, see LICENSE for details. 20 | * 21 | */ 22 | 23 | $(function() { 24 | // global elements used by the functions. 25 | // the 'sidebarbutton' element is defined as global after its 26 | // creation, in the add_sidebar_button function 27 | var bodywrapper = $('.bodywrapper'); 28 | var sidebar = $('.sphinxsidebar'); 29 | var sidebarwrapper = $('.sphinxsidebarwrapper'); 30 | 31 | // original margin-left of the bodywrapper and width of the sidebar 32 | // with the sidebar expanded 33 | var bw_margin_expanded = bodywrapper.css('margin-left'); 34 | var ssb_width_expanded = sidebar.width(); 35 | 36 | // margin-left of the bodywrapper and width of the sidebar 37 | // with the sidebar collapsed 38 | var bw_margin_collapsed = '.8em'; 39 | var ssb_width_collapsed = '.8em'; 40 | 41 | // colors used by the current theme 42 | var dark_color = '#AAAAAA'; 43 | var light_color = '#CCCCCC'; 44 | 45 | function sidebar_is_collapsed() { 46 | return sidebarwrapper.is(':not(:visible)'); 47 | } 48 | 49 | function toggle_sidebar() { 50 | if (sidebar_is_collapsed()) 51 | expand_sidebar(); 52 | else 53 | collapse_sidebar(); 54 | } 55 | 56 | function collapse_sidebar() { 57 | sidebarwrapper.hide(); 58 | sidebar.css('width', ssb_width_collapsed); 59 | bodywrapper.css('margin-left', bw_margin_collapsed); 60 | sidebarbutton.css({ 61 | 'margin-left': '0', 62 | 'height': bodywrapper.height(), 63 | 'border-radius': '5px' 64 | }); 65 | sidebarbutton.find('span').text('»'); 66 | sidebarbutton.attr('title', _('Expand sidebar')); 67 | document.cookie = 'sidebar=collapsed'; 68 | } 69 | 70 | function expand_sidebar() { 71 | bodywrapper.css('margin-left', bw_margin_expanded); 72 | sidebar.css('width', ssb_width_expanded); 73 | sidebarwrapper.show(); 74 | sidebarbutton.css({ 75 | 'margin-left': ssb_width_expanded-12, 76 | 'height': bodywrapper.height(), 77 | 'border-radius': '0 5px 5px 0' 78 | }); 79 | sidebarbutton.find('span').text('«'); 80 | sidebarbutton.attr('title', _('Collapse sidebar')); 81 | //sidebarwrapper.css({'padding-top': 82 | // Math.max(window.pageYOffset - sidebarwrapper.offset().top, 10)}); 83 | document.cookie = 'sidebar=expanded'; 84 | } 85 | 86 | function add_sidebar_button() { 87 | sidebarwrapper.css({ 88 | 'float': 'left', 89 | 'margin-right': '0', 90 | 'width': ssb_width_expanded - 28 91 | }); 92 | // create the button 93 | sidebar.append( 94 | '
«
' 95 | ); 96 | var sidebarbutton = $('#sidebarbutton'); 97 | // find the height of the viewport to center the '<<' in the page 98 | var viewport_height; 99 | if (window.innerHeight) 100 | viewport_height = window.innerHeight; 101 | else 102 | viewport_height = $(window).height(); 103 | var sidebar_offset = sidebar.offset().top; 104 | var sidebar_height = Math.max(bodywrapper.height(), sidebar.height()); 105 | sidebarbutton.find('span').css({ 106 | 'display': 'block', 107 | 'position': 'fixed', 108 | 'top': Math.min(viewport_height/2, sidebar_height/2 + sidebar_offset) - 10 109 | }); 110 | 111 | sidebarbutton.click(toggle_sidebar); 112 | sidebarbutton.attr('title', _('Collapse sidebar')); 113 | sidebarbutton.css({ 114 | 'border-radius': '0 5px 5px 0', 115 | 'color': '#444444', 116 | 'background-color': '#CCCCCC', 117 | 'font-size': '1.2em', 118 | 'cursor': 'pointer', 119 | 'height': sidebar_height, 120 | 'padding-top': '1px', 121 | 'padding-left': '1px', 122 | 'margin-left': ssb_width_expanded - 12 123 | }); 124 | 125 | sidebarbutton.hover( 126 | function () { 127 | $(this).css('background-color', dark_color); 128 | }, 129 | function () { 130 | $(this).css('background-color', light_color); 131 | } 132 | ); 133 | } 134 | 135 | function set_position_from_cookie() { 136 | if (!document.cookie) 137 | return; 138 | var items = document.cookie.split(';'); 139 | for(var k=0; k v documentation". 132 | #html_title = None 133 | 134 | # A shorter title for the navigation bar. Default is the same as html_title. 135 | #html_short_title = None 136 | 137 | # The name of an image file (relative to this directory) to place at the top 138 | # of the sidebar. 139 | #html_logo = None 140 | 141 | # The name of an image file (within the static path) to use as favicon of the 142 | # docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 143 | # pixels large. 144 | #html_favicon = None 145 | 146 | # Add any paths that contain custom static files (such as style sheets) here, 147 | # relative to this directory. They are copied after the builtin static files, 148 | # so a file named "default.css" will overwrite the builtin "default.css". 149 | html_static_path = ['_static'] 150 | 151 | # If not '', a 'Last updated on:' timestamp is inserted at every page bottom, 152 | # using the given strftime format. 153 | #html_last_updated_fmt = '%b %d, %Y' 154 | 155 | # If true, SmartyPants will be used to convert quotes and dashes to 156 | # typographically correct entities. 157 | #html_use_smartypants = True 158 | 159 | # Custom sidebar templates, maps document names to template names. 160 | 161 | # html_sidebars = { 162 | # '**': [ 163 | # 'localtoc.html', 'globaltoc.html', 'relations.html', 164 | # 'sourcelink.html', 'searchbox.html' 165 | # ], 166 | # } 167 | 168 | # Additional templates that should be rendered to pages, maps page names to 169 | # template names. 170 | #html_additional_pages = {} 171 | 172 | # If false, no module index is generated. 173 | # html_domain_indices = True 174 | 175 | # If false, no index is generated. 176 | #html_use_index = True 177 | 178 | # If true, the index is split into individual pages for each letter. 179 | #html_split_index = False 180 | 181 | # If true, links to the reST sources are added to the pages. 182 | #html_show_sourcelink = True 183 | 184 | # If true, "Created using Sphinx" is shown in the HTML footer. Default is True. 185 | #html_show_sphinx = True 186 | 187 | # If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. 188 | #html_show_copyright = True 189 | 190 | # If true, an OpenSearch description file will be output, and all pages will 191 | # contain a tag referring to it. The value of this option must be the 192 | # base URL from which the finished HTML is served. 193 | #html_use_opensearch = '' 194 | 195 | # This is the file name suffix for HTML files (e.g. ".xhtml"). 196 | #html_file_suffix = None 197 | 198 | # Output file base name for HTML help builder. 199 | htmlhelp_basename = 'GnuPGWrapperforPythondoc' 200 | 201 | # -- Options for LaTeX output -------------------------------------------------- 202 | 203 | # The paper size ('letter' or 'a4'). 204 | #latex_paper_size = 'letter' 205 | 206 | # The font size ('10pt', '11pt' or '12pt'). 207 | #latex_font_size = '10pt' 208 | 209 | # Grouping the document tree into LaTeX files. List of tuples 210 | # (source start file, target name, title, author, documentclass [howto/manual]). 211 | latex_documents = [ 212 | ('index', 'GnuPGWrapperforPython.tex', u'GnuPG Wrapper for Python Documentation', u'Vinay Sajip', 'manual'), 213 | ] 214 | 215 | # The name of an image file (relative to this directory) to place at the top of 216 | # the title page. 217 | #latex_logo = None 218 | 219 | # For "manual" documents, if this is true, then toplevel headings are parts, 220 | # not chapters. 221 | #latex_use_parts = False 222 | 223 | # If true, show page references after internal links. 224 | #latex_show_pagerefs = False 225 | 226 | # If true, show URL addresses after external links. 227 | #latex_show_urls = False 228 | 229 | # Additional stuff for the LaTeX preamble. 230 | #latex_preamble = '' 231 | 232 | # Documents to append as an appendix to all manuals. 233 | #latex_appendices = [] 234 | 235 | # If false, no module index is generated. 236 | #latex_domain_indices = True 237 | 238 | # -- Options for manual page output -------------------------------------------- 239 | 240 | # One entry per manual page. List of tuples 241 | # (source start file, name, description, authors, manual section). 242 | man_pages = [('index', 'python-gnupg', u'python-gnupg Documentation', [u'Vinay Sajip'], 1)] 243 | 244 | # -- Options for Epub output --------------------------------------------------- 245 | 246 | # Bibliographic Dublin Core info. 247 | epub_title = u'python-gnupg' 248 | epub_author = u'Vinay Sajip' 249 | epub_publisher = u'Vinay Sajip' 250 | epub_copyright = u'2019, Vinay Sajip' 251 | 252 | # The language of the text. It defaults to the language option 253 | # or en if the language is not set. 254 | #epub_language = '' 255 | 256 | # The scheme of the identifier. Typical schemes are ISBN or URL. 257 | #epub_scheme = '' 258 | 259 | # The unique identifier of the text. This can be a ISBN number 260 | # or the project homepage. 261 | #epub_identifier = '' 262 | 263 | # A unique identification for the text. 264 | #epub_uid = '' 265 | 266 | # HTML files that should be inserted before the pages created by sphinx. 267 | # The format is a list of tuples containing the path and title. 268 | #epub_pre_files = [] 269 | 270 | # HTML files shat should be inserted after the pages created by sphinx. 271 | # The format is a list of tuples containing the path and title. 272 | #epub_post_files = [] 273 | 274 | # A list of files that should not be packed into the epub file. 275 | #epub_exclude_files = [] 276 | 277 | # The depth of the table of contents in toc.ncx. 278 | #epub_tocdepth = 3 279 | 280 | # Allow duplicate toc entries. 281 | #epub_tocdup = True 282 | 283 | # Example configuration for intersphinx: refer to the Python standard library. 284 | intersphinx_mapping = {'python': ('http://docs.python.org/', None)} 285 | 286 | 287 | def skip_module_docstring(app, what, name, obj, options, lines): 288 | if (what, name) == ('module', 'distlib'): 289 | del lines[:] 290 | 291 | 292 | def setup(app): 293 | app.connect('autodoc-process-docstring', skip_module_docstring) 294 | -------------------------------------------------------------------------------- /messages.json: -------------------------------------------------------------------------------- 1 | { 2 | "0000": "Success", 3 | "0001": "General error", 4 | "0002": "Unknown packet", 5 | "0003": "Unknown version in packet", 6 | "0004": "Invalid public key algorithm", 7 | "0005": "Invalid digest algorithm", 8 | "0006": "Bad public key", 9 | "0007": "Bad secret key", 10 | "0008": "Bad signature", 11 | "0009": "No public key", 12 | "000A": "Checksum error", 13 | "000B": "Bad passphrase", 14 | "000C": "Invalid cipher algorithm", 15 | "000D": "Cannot open keyring", 16 | "000E": "Invalid packet", 17 | "000F": "Invalid armor", 18 | "0010": "No user ID", 19 | "0011": "No secret key", 20 | "0012": "Wrong secret key used", 21 | "0013": "Bad session key", 22 | "0014": "Unknown compression algorithm", 23 | "0015": "Number is not prime", 24 | "0016": "Invalid encoding method", 25 | "0017": "Invalid encryption scheme", 26 | "0018": "Invalid signature scheme", 27 | "0019": "Invalid attribute", 28 | "001A": "No value", 29 | "001B": "Not found", 30 | "001C": "Value not found", 31 | "001D": "Syntax error", 32 | "001E": "Bad MPI value", 33 | "001F": "Invalid passphrase", 34 | "0020": "Invalid signature class", 35 | "0021": "Resources exhausted", 36 | "0022": "Invalid keyring", 37 | "0023": "Trust DB error", 38 | "0024": "Bad certificate", 39 | "0025": "Invalid user ID", 40 | "0026": "Unexpected error", 41 | "0027": "Time conflict", 42 | "0028": "Keyserver error", 43 | "0029": "Wrong public key algorithm", 44 | "002A": "Tribute to D. A.", 45 | "002B": "Weak encryption key", 46 | "002C": "Invalid key length", 47 | "002D": "Invalid argument", 48 | "002E": "Syntax error in URI", 49 | "002F": "Invalid URI", 50 | "0030": "Network error", 51 | "0031": "Unknown host", 52 | "0032": "Selftest failed", 53 | "0033": "Data not encrypted", 54 | "0034": "Data not processed", 55 | "0035": "Unusable public key", 56 | "0036": "Unusable secret key", 57 | "0037": "Invalid value", 58 | "0038": "Bad certificate chain", 59 | "0039": "Missing certificate", 60 | "003A": "No data", 61 | "003B": "Bug", 62 | "003C": "Not supported", 63 | "003D": "Invalid operation code", 64 | "003E": "Timeout", 65 | "003F": "Internal error", 66 | "0040": "EOF (gcrypt)", 67 | "0041": "Invalid object", 68 | "0042": "Provided object is too short", 69 | "0043": "Provided object is too large", 70 | "0044": "Missing item in object", 71 | "0045": "Not implemented", 72 | "0046": "Conflicting use", 73 | "0047": "Invalid cipher mode", 74 | "0048": "Invalid flag", 75 | "0049": "Invalid handle", 76 | "004A": "Result truncated", 77 | "004B": "Incomplete line", 78 | "004C": "Invalid response", 79 | "004D": "No agent running", 80 | "004E": "Agent error", 81 | "004F": "Invalid data", 82 | "0050": "Unspecific Assuan server fault", 83 | "0051": "General Assuan error", 84 | "0052": "Invalid session key", 85 | "0053": "Invalid S-expression", 86 | "0054": "Unsupported algorithm", 87 | "0055": "No pinentry", 88 | "0056": "pinentry error", 89 | "0057": "Bad PIN", 90 | "0058": "Invalid name", 91 | "0059": "Bad data", 92 | "005A": "Invalid parameter", 93 | "005B": "Wrong card", 94 | "005C": "No dirmngr", 95 | "005D": "dirmngr error", 96 | "005E": "Certificate revoked", 97 | "005F": "No CRL known", 98 | "0060": "CRL too old", 99 | "0061": "Line too long", 100 | "0062": "Not trusted", 101 | "0063": "Operation cancelled", 102 | "0064": "Bad CA certificate", 103 | "0065": "Certificate expired", 104 | "0066": "Certificate too young", 105 | "0067": "Unsupported certificate", 106 | "0068": "Unknown S-expression", 107 | "0069": "Unsupported protection", 108 | "006A": "Corrupted protection", 109 | "006B": "Ambiguous name", 110 | "006C": "Card error", 111 | "006D": "Card reset required", 112 | "006E": "Card removed", 113 | "006F": "Invalid card", 114 | "0070": "Card not present", 115 | "0071": "No PKCS15 application", 116 | "0072": "Not confirmed", 117 | "0073": "Configuration error", 118 | "0074": "No policy match", 119 | "0075": "Invalid index", 120 | "0076": "Invalid ID", 121 | "0077": "No SmartCard daemon", 122 | "0078": "SmartCard daemon error", 123 | "0079": "Unsupported protocol", 124 | "007A": "Bad PIN method", 125 | "007B": "Card not initialized", 126 | "007C": "Unsupported operation", 127 | "007D": "Wrong key usage", 128 | "007E": "Nothing found", 129 | "007F": "Wrong blob type", 130 | "0080": "Missing value", 131 | "0081": "Hardware problem", 132 | "0082": "PIN blocked", 133 | "0083": "Conditions of use not satisfied", 134 | "0084": "PINs are not synced", 135 | "0085": "Invalid CRL", 136 | "0086": "BER error", 137 | "0087": "Invalid BER", 138 | "0088": "Element not found", 139 | "0089": "Identifier not found", 140 | "008A": "Invalid tag", 141 | "008B": "Invalid length", 142 | "008C": "Invalid key info", 143 | "008D": "Unexpected tag", 144 | "008E": "Not DER encoded", 145 | "008F": "No CMS object", 146 | "0090": "Invalid CMS object", 147 | "0091": "Unknown CMS object", 148 | "0092": "Unsupported CMS object", 149 | "0093": "Unsupported encoding", 150 | "0094": "Unsupported CMS version", 151 | "0095": "Unknown algorithm", 152 | "0096": "Invalid crypto engine", 153 | "0097": "Public key not trusted", 154 | "0098": "Decryption failed", 155 | "0099": "Key expired", 156 | "009A": "Signature expired", 157 | "009B": "Encoding problem", 158 | "009C": "Invalid state", 159 | "009D": "Duplicated value", 160 | "009E": "Missing action", 161 | "009F": "ASN.1 module not found", 162 | "00A0": "Invalid OID string", 163 | "00A1": "Invalid time", 164 | "00A2": "Invalid CRL object", 165 | "00A3": "Unsupported CRL version", 166 | "00A4": "Invalid certificate object", 167 | "00A5": "Unknown name", 168 | "00A6": "A locale function failed", 169 | "00A7": "Not locked", 170 | "00A8": "Protocol violation", 171 | "00A9": "Invalid MAC", 172 | "00AA": "Invalid request", 173 | "00AB": "Unknown extension", 174 | "00AC": "Unknown critical extension", 175 | "00AD": "Locked", 176 | "00AE": "Unknown option", 177 | "00AF": "Unknown command", 178 | "00B0": "Not operational", 179 | "00B1": "No passphrase given", 180 | "00B2": "No PIN given", 181 | "00B3": "Not enabled", 182 | "00B4": "No crypto engine", 183 | "00B5": "Missing key", 184 | "00B6": "Too many objects", 185 | "00B7": "Limit reached", 186 | "00B8": "Not initialized", 187 | "00B9": "Missing issuer certificate", 188 | "00BA": "No keyserver available", 189 | "00BB": "Invalid elliptic curve", 190 | "00BC": "Unknown elliptic curve", 191 | "00BD": "Duplicated key", 192 | "00BE": "Ambiguous result", 193 | "00BF": "No crypto context", 194 | "00C0": "Wrong crypto context", 195 | "00C1": "Bad crypto context", 196 | "00C2": "Conflict in the crypto context", 197 | "00C3": "Broken public key", 198 | "00C4": "Broken secret key", 199 | "00C5": "Invalid MAC algorithm", 200 | "00C6": "Operation fully cancelled", 201 | "00C7": "Operation not yet finished", 202 | "00C8": "Buffer too short", 203 | "00C9": "Invalid length specifier in S-expression", 204 | "00CA": "String too long in S-expression", 205 | "00CB": "Unmatched parentheses in S-expression", 206 | "00CC": "S-expression not canonical", 207 | "00CD": "Bad character in S-expression", 208 | "00CE": "Bad quotation in S-expression", 209 | "00CF": "Zero prefix in S-expression", 210 | "00D0": "Nested display hints in S-expression", 211 | "00D1": "Unmatched display hints", 212 | "00D2": "Unexpected reserved punctuation in S-expression", 213 | "00D3": "Bad hexadecimal character in S-expression", 214 | "00D4": "Odd hexadecimal numbers in S-expression", 215 | "00D5": "Bad octal character in S-expression", 216 | "00D9": "All subkeys are expired or revoked", 217 | "00DA": "Database is corrupted", 218 | "00DB": "Server indicated a failure", 219 | "00DC": "No name", 220 | "00DD": "No key", 221 | "00DE": "Legacy key", 222 | "00DF": "Request too short", 223 | "00E0": "Request too long", 224 | "00E1": "Object is in termination state", 225 | "00E2": "No certificate chain", 226 | "00E3": "Certificate is too large", 227 | "00E4": "Invalid record", 228 | "00E5": "The MAC does not verify", 229 | "00E6": "Unexpected message", 230 | "00E7": "Compression or decompression failed", 231 | "00E8": "A counter would wrap", 232 | "00E9": "Fatal alert message received", 233 | "00EA": "No cipher algorithm", 234 | "00EB": "Missing client certificate", 235 | "00EC": "Close notification received", 236 | "00ED": "Ticket expired", 237 | "00EE": "Bad ticket", 238 | "00EF": "Unknown identity", 239 | "00F0": "Bad certificate message in handshake", 240 | "00F1": "Bad certificate request message in handshake", 241 | "00F2": "Bad certificate verify message in handshake", 242 | "00F3": "Bad change cipher message in handshake", 243 | "00F4": "Bad client hello message in handshake", 244 | "00F5": "Bad server hello message in handshake", 245 | "00F6": "Bad server hello done message in handshake", 246 | "00F7": "Bad finished message in handshake", 247 | "00F8": "Bad server key exchange message in handshake", 248 | "00F9": "Bad client key exchange message in handshake", 249 | "00FA": "Bogus string", 250 | "00FB": "Forbidden", 251 | "00FC": "Key disabled", 252 | "00FD": "Not possible with a card based key", 253 | "00FE": "Invalid lock object", 254 | "00FF": "True", 255 | "0100": "False", 256 | "0101": "General IPC error", 257 | "0102": "IPC accept call failed", 258 | "0103": "IPC connect call failed", 259 | "0104": "Invalid IPC response", 260 | "0105": "Invalid value passed to IPC", 261 | "0106": "Incomplete line passed to IPC", 262 | "0107": "Line passed to IPC too long", 263 | "0108": "Nested IPC commands", 264 | "0109": "No data callback in IPC", 265 | "010A": "No inquire callback in IPC", 266 | "010B": "Not an IPC server", 267 | "010C": "Not an IPC client", 268 | "010D": "Problem starting IPC server", 269 | "010E": "IPC read error", 270 | "010F": "IPC write error", 271 | "0111": "Too much data for IPC layer", 272 | "0112": "Unexpected IPC command", 273 | "0113": "Unknown IPC command", 274 | "0114": "IPC syntax error", 275 | "0115": "IPC call has been cancelled", 276 | "0116": "No input source for IPC", 277 | "0117": "No output source for IPC", 278 | "0118": "IPC parameter error", 279 | "0119": "Unknown IPC inquire", 280 | "012C": "Crypto engine too old", 281 | "012D": "Screen or window too small", 282 | "012E": "Screen or window too large", 283 | "012F": "Required environment variable not set", 284 | "0130": "User ID already exists", 285 | "0131": "Name already exists", 286 | "0132": "Duplicated name", 287 | "0133": "Object is too young", 288 | "0134": "Object is too old", 289 | "0135": "Unknown flag", 290 | "0136": "Invalid execution order", 291 | "0137": "Already fetched", 292 | "0138": "Try again later", 293 | "0139": "Wrong name", 294 | "013A": "Not authenticated", 295 | "013B": "Bad authentication", 296 | "013C": "No Keybox daemon running", 297 | "013D": "Keybox daemon error", 298 | "013E": "Service is not running", 299 | "013F": "Service error", 300 | "029A": "System bug detected", 301 | "02C7": "Unknown DNS error", 302 | "02C8": "Invalid DNS section", 303 | "02C9": "Invalid textual address form", 304 | "02CA": "Missing DNS query packet", 305 | "02CB": "Missing DNS answer packet", 306 | "02CC": "Connection closed in DNS", 307 | "02CD": "Verification failed in DNS", 308 | "02CE": "DNS Timeout", 309 | "02D1": "General LDAP error", 310 | "02D2": "General LDAP attribute error", 311 | "02D3": "General LDAP name error", 312 | "02D4": "General LDAP security error", 313 | "02D5": "General LDAP service error", 314 | "02D6": "General LDAP update error", 315 | "02D7": "Experimental LDAP error code", 316 | "02D8": "Private LDAP error code", 317 | "02D9": "Other general LDAP error", 318 | "02EE": "LDAP connecting failed (X)", 319 | "02EF": "LDAP referral limit exceeded", 320 | "02F0": "LDAP client loop", 321 | "02F2": "No LDAP results returned", 322 | "02F3": "LDAP control not found", 323 | "02F4": "Not supported by LDAP", 324 | "02F5": "LDAP connect error", 325 | "02F6": "Out of memory in LDAP", 326 | "02F7": "Bad parameter to an LDAP routine", 327 | "02F8": "User cancelled LDAP operation", 328 | "02F9": "Bad LDAP search filter", 329 | "02FA": "Unknown LDAP authentication method", 330 | "02FB": "Timeout in LDAP", 331 | "02FC": "LDAP decoding error", 332 | "02FD": "LDAP encoding error", 333 | "02FE": "LDAP local error", 334 | "02FF": "Cannot contact LDAP server", 335 | "0300": "LDAP success", 336 | "0301": "LDAP operations error", 337 | "0302": "LDAP protocol error", 338 | "0303": "Time limit exceeded in LDAP", 339 | "0304": "Size limit exceeded in LDAP", 340 | "0305": "LDAP compare false", 341 | "0306": "LDAP compare true", 342 | "0307": "LDAP authentication method not supported", 343 | "0308": "Strong(er) LDAP authentication required", 344 | "0309": "Partial LDAP results+referral received", 345 | "030A": "LDAP referral", 346 | "030B": "Administrative LDAP limit exceeded", 347 | "030C": "Critical LDAP extension is unavailable", 348 | "030D": "Confidentiality required by LDAP", 349 | "030E": "LDAP SASL bind in progress", 350 | "0310": "No such LDAP attribute", 351 | "0311": "Undefined LDAP attribute type", 352 | "0312": "Inappropriate matching in LDAP", 353 | "0313": "Constraint violation in LDAP", 354 | "0314": "LDAP type or value exists", 355 | "0315": "Invalid syntax in LDAP", 356 | "0320": "No such LDAP object", 357 | "0321": "LDAP alias problem", 358 | "0322": "Invalid DN syntax in LDAP", 359 | "0323": "LDAP entry is a leaf", 360 | "0324": "LDAP alias dereferencing problem", 361 | "032F": "LDAP proxy authorization failure (X)", 362 | "0330": "Inappropriate LDAP authentication", 363 | "0331": "Invalid LDAP credentials", 364 | "0332": "Insufficient access for LDAP", 365 | "0333": "LDAP server is busy", 366 | "0334": "LDAP server is unavailable", 367 | "0335": "LDAP server is unwilling to perform", 368 | "0336": "Loop detected by LDAP", 369 | "0340": "LDAP naming violation", 370 | "0341": "LDAP object class violation", 371 | "0342": "LDAP operation not allowed on non-leaf", 372 | "0343": "LDAP operation not allowed on RDN", 373 | "0344": "Already exists (LDAP)", 374 | "0345": "Cannot modify LDAP object class", 375 | "0346": "LDAP results too large", 376 | "0347": "LDAP operation affects multiple DSAs", 377 | "034C": "Virtual LDAP list view error", 378 | "0350": "Other LDAP error", 379 | "0371": "Resources exhausted in LCUP", 380 | "0372": "Security violation in LCUP", 381 | "0373": "Invalid data in LCUP", 382 | "0374": "Unsupported scheme in LCUP", 383 | "0375": "Reload required in LCUP", 384 | "0376": "LDAP cancelled", 385 | "0377": "No LDAP operation to cancel", 386 | "0378": "Too late to cancel LDAP", 387 | "0379": "Cannot cancel LDAP", 388 | "037A": "LDAP assertion failed", 389 | "037B": "Proxied authorization denied by LDAP", 390 | "0400": "User defined error code 1", 391 | "0401": "User defined error code 2", 392 | "0402": "User defined error code 3", 393 | "0403": "User defined error code 4", 394 | "0404": "User defined error code 5", 395 | "0405": "User defined error code 6", 396 | "0406": "User defined error code 7", 397 | "0407": "User defined error code 8", 398 | "0408": "User defined error code 9", 399 | "0409": "User defined error code 10", 400 | "040A": "User defined error code 11", 401 | "040B": "User defined error code 12", 402 | "040C": "User defined error code 13", 403 | "040D": "User defined error code 14", 404 | "040E": "User defined error code 15", 405 | "040F": "User defined error code 16", 406 | "05DC": "SQL success", 407 | "05DD": "SQL error", 408 | "05DE": "Internal logic error in SQL library", 409 | "05DF": "Access permission denied (SQL)", 410 | "05E0": "SQL abort was requested", 411 | "05E1": "SQL database file is locked", 412 | "05E2": "An SQL table in the database is locked", 413 | "05E3": "SQL library ran out of core", 414 | "05E4": "Attempt to write a readonly SQL database", 415 | "05E5": "SQL operation terminated by interrupt", 416 | "05E6": "I/O error during SQL operation", 417 | "05E7": "SQL database disk image is malformed", 418 | "05E8": "Unknown opcode in SQL file control", 419 | "05E9": "Insertion failed because SQL database is full", 420 | "05EA": "Unable to open the SQL database file", 421 | "05EB": "SQL database lock protocol error", 422 | "05EC": "(internal SQL code: empty)", 423 | "05ED": "SQL database schema changed", 424 | "05EE": "String or blob exceeds size limit (SQL)", 425 | "05EF": "SQL abort due to constraint violation", 426 | "05F0": "Data type mismatch (SQL)", 427 | "05F1": "SQL library used incorrectly", 428 | "05F2": "SQL library uses unsupported OS features", 429 | "05F3": "Authorization denied (SQL)", 430 | "05F4": "(unused SQL code: format)", 431 | "05F5": "SQL bind parameter out of range", 432 | "05F6": "File opened that is not an SQL database file", 433 | "05F7": "Notifications from SQL logger", 434 | "05F8": "Warnings from SQL logger", 435 | "0640": "SQL has another row ready", 436 | "0641": "SQL has finished executing", 437 | "3FFD": "System error w/o errno", 438 | "3FFF": "End of file", 439 | "8000": "Argument list too long", 440 | "8001": "Permission denied", 441 | "8002": "Address already in use", 442 | "8003": "Cannot assign requested address", 443 | "8004": "Advertise error", 444 | "8005": "Address family not supported by protocol", 445 | "8006": "Resource temporarily unavailable", 446 | "8007": "Operation already in progress", 447 | "800A": "Invalid exchange", 448 | "800B": "Bad file descriptor", 449 | "800C": "File descriptor in bad state", 450 | "800D": "Bad message", 451 | "800E": "Invalid request descriptor", 452 | "8010": "Invalid request code", 453 | "8011": "Invalid slot", 454 | "8012": "Bad font file format", 455 | "8013": "Device or resource busy", 456 | "8014": "Operation canceled", 457 | "8015": "No child processes", 458 | "8016": "Channel number out of range", 459 | "8017": "Communication error on send", 460 | "8018": "Software caused connection abort", 461 | "8019": "Connection refused", 462 | "801A": "Connection reset by peer", 463 | "801C": "Resource deadlock avoided", 464 | "801D": "Resource deadlock avoided", 465 | "801E": "Destination address required", 466 | "8020": "Numerical argument out of domain", 467 | "8021": "RFS specific error", 468 | "8022": "Disk quota exceeded", 469 | "8023": "File exists", 470 | "8024": "Bad address", 471 | "8025": "File too large", 472 | "8029": "Host is down", 473 | "802A": "No route to host", 474 | "802B": "Identifier removed", 475 | "802D": "Invalid or incomplete multibyte or wide character", 476 | "802E": "Operation now in progress", 477 | "802F": "Interrupted system call", 478 | "8030": "Invalid argument", 479 | "8031": "Input/output error", 480 | "8032": "Transport endpoint is already connected", 481 | "8033": "Is a directory", 482 | "8034": "Is a named type file", 483 | "8035": "Level 2 halted", 484 | "8036": "Level 2 not synchronized", 485 | "8037": "Level 3 halted", 486 | "8038": "Level 3 reset", 487 | "8039": "Can not access a needed shared library", 488 | "803A": "Accessing a corrupted shared library", 489 | "803B": "Cannot exec a shared library directly", 490 | "803C": "Attempting to link in too many shared libraries", 491 | "803D": ".lib section in a.out corrupted", 492 | "803E": "Link number out of range", 493 | "803F": "Too many levels of symbolic links", 494 | "8040": "Wrong medium type", 495 | "8041": "Too many open files", 496 | "8042": "Too many links", 497 | "8043": "Message too long", 498 | "8044": "Multihop attempted", 499 | "8045": "File name too long", 500 | "8046": "No XENIX semaphores available", 501 | "8048": "Network is down", 502 | "8049": "Network dropped connection on reset", 503 | "804A": "Network is unreachable", 504 | "804B": "Too many open files in system", 505 | "804C": "No anode", 506 | "804D": "No buffer space available", 507 | "804E": "No CSI structure available", 508 | "804F": "No data available", 509 | "8050": "No such device", 510 | "8051": "No such file or directory", 511 | "8052": "Exec format error", 512 | "8053": "No locks available", 513 | "8054": "Link has been severed", 514 | "8055": "No medium found", 515 | "8056": "Cannot allocate memory", 516 | "8057": "No message of desired type", 517 | "8058": "Machine is not on the network", 518 | "8059": "Package not installed", 519 | "805A": "Protocol not available", 520 | "805B": "No space left on device", 521 | "805C": "Out of streams resources", 522 | "805D": "Device not a stream", 523 | "805E": "Function not implemented", 524 | "805F": "Block device required", 525 | "8060": "Transport endpoint is not connected", 526 | "8061": "Not a directory", 527 | "8062": "Directory not empty", 528 | "8063": "Not a XENIX named type file", 529 | "8064": "Socket operation on non-socket", 530 | "8065": "Operation not supported", 531 | "8066": "Inappropriate ioctl for device", 532 | "8067": "Name not unique on network", 533 | "8068": "No such device or address", 534 | "8069": "Operation not supported", 535 | "806A": "Value too large for defined data type", 536 | "806B": "Operation not permitted", 537 | "806C": "Protocol family not supported", 538 | "806D": "Broken pipe", 539 | "8072": "Protocol error", 540 | "8073": "Protocol not supported", 541 | "8074": "Protocol wrong type for socket", 542 | "8075": "Numerical result out of range", 543 | "8076": "Remote address changed", 544 | "8077": "Object is remote", 545 | "8078": "Remote I/O error", 546 | "8079": "Interrupted system call should be restarted", 547 | "807A": "Read-only file system", 548 | "807C": "Cannot send after transport endpoint shutdown", 549 | "807D": "Socket type not supported", 550 | "807E": "Illegal seek", 551 | "807F": "No such process", 552 | "8080": "Srmount error", 553 | "8081": "Stale file handle", 554 | "8082": "Streams pipe error", 555 | "8083": "Timer expired", 556 | "8084": "Connection timed out", 557 | "8085": "Too many references: cannot splice", 558 | "8086": "Text file busy", 559 | "8087": "Structure needs cleaning", 560 | "8088": "Protocol driver not attached", 561 | "8089": "Too many users", 562 | "808A": "Resource temporarily unavailable", 563 | "808B": "Invalid cross-device link", 564 | "808C": "Exchange full" 565 | } 566 | -------------------------------------------------------------------------------- /README.rst: -------------------------------------------------------------------------------- 1 | |badge1| |badge2| |badge3| 2 | 3 | .. |badge1| image:: https://img.shields.io/github/actions/workflow/status/vsajip/python-gnupg/python-package.yml 4 | :alt: GitHub test status 5 | 6 | .. |badge2| image:: https://img.shields.io/codecov/c/github/vsajip/python-gnupg 7 | :target: https://app.codecov.io/gh/vsajip/python-gnupg 8 | :alt: GitHub coverage status 9 | 10 | .. |badge3| image:: https://img.shields.io/pypi/v/python-gnupg 11 | :target: https://pypi.org/project/python-gnupg/ 12 | :alt: PyPI package 13 | 14 | 15 | What is it? 16 | =========== 17 | 18 | The GNU Privacy Guard (gpg, or gpg.exe on Windows) is a command-line program 19 | which provides support for programmatic access via spawning a separate process 20 | to run it and then communicating with that process from your program. 21 | 22 | This project, ``python-gnupg``, implements a Python library which takes care 23 | of the internal details and allows its users to generate and manage keys, 24 | encrypt and decrypt data, and sign and verify messages. 25 | 26 | Installation 27 | ============ 28 | 29 | Installing from PyPI 30 | -------------------- 31 | 32 | You can install this package from the Python Package Index (pyPI) by running:: 33 | 34 | pip install python-gnupg 35 | 36 | .. important:: 37 | There is at least one fork of this project, which was apparently created 38 | because an earlier version of this software used the ``subprocess`` module 39 | with ``shell=True``, making it vulnerable to shell injection. **This is no 40 | longer the case**. 41 | 42 | Forks may not be drop-in compatible with this software, so take care to use 43 | the correct version, as indicated in the ``pip install`` command above. 44 | 45 | 46 | Installing from a source distribution archive 47 | --------------------------------------------- 48 | To install this package from a source distribution archive, do the following: 49 | 50 | 1. Extract all the files in the distribution archive to some directory on your 51 | system. 52 | 2. In that directory, run ``pip install .``, referencing a suitable ``pip`` (e.g. one 53 | from a specific venv which you want to install to). 54 | 3. Optionally, run ``python test_gnupg.py`` to ensure that the package is 55 | working as expected. 56 | 57 | Credits 58 | ======= 59 | 60 | * The developers of the GNU Privacy Guard. 61 | * The original version of this module was developed by Andrew Kuchling. 62 | * It was improved by Richard Jones. 63 | * It was further improved by Steve Traugott. 64 | 65 | The present incarnation, based on the earlier versions, uses the ``subprocess`` 66 | module and so works on Windows as well as Unix/Linux platforms. It's not, 67 | however, 100% backwards-compatible with earlier incarnations. 68 | 69 | Change log 70 | ========== 71 | 72 | .. note:: GCnn refers to an issue nn on Google Code. 73 | 74 | 75 | 0.5.6 (future) 76 | -------------- 77 | 78 | Released: Not yet 79 | 80 | * Fix #261: Ensure fingerprint and keygrip are added to subkey_info. 81 | 82 | * Set username in the result when Verify uses a signing key that has expired or been 83 | revoked. Thanks to Steven Galgano for the patch. 84 | 85 | 0.5.5 86 | ----- 87 | 88 | Released: 2025-08-04 89 | 90 | * Fix #249: Handle fetching GPG version when not the first item in the configuration. 91 | 92 | * Fix #250: Capture uid info in a uid_map attribute of ScanKeys/ListKeys. 93 | 94 | * Fix #255: Improve handling of exceptions raised in background threads. 95 | 96 | 97 | 0.5.4 98 | ----- 99 | 100 | Released: 2025-01-07 101 | 102 | * Fix #242: Handle exceptions in ``on_data`` callable. 103 | 104 | 105 | 0.5.3 106 | ----- 107 | 108 | Released: 2024-09-20 109 | 110 | * Fix #117: Add WKD (Web Key Directory) support for auto-locating keys. Thanks to Myzel394 111 | for the patch. 112 | 113 | * Fix #237: Ensure local variable is initialized even when an exception occurs. 114 | 115 | * Fix #239: Remove logging of decryption result. 116 | 117 | 118 | 0.5.2 119 | ----- 120 | 121 | Released: 2023-12-12 122 | 123 | * Fix #228: Clarify documentation for encryption/decryption. 124 | 125 | * Make I/O buffer size configurable via ``buffer_size`` attribute on a ``GPG`` instance. 126 | 127 | 128 | 0.5.1 129 | ----- 130 | 131 | Released: 2023-07-22 132 | 133 | * Added ``TRUST_EXPIRED`` to ``trust_keys``. Thanks to Leif Liddy for the patch. 134 | 135 | * Fix #206: Remove deprecated ``--always-trust`` in favour of ``--trust-model always`` 136 | 137 | * Fix #208: Add ``status_detail`` attribute to result objects which is populated when 138 | the status is ``'invalid recipient'`` (encryption/decryption) or ``'invalid signer'`` 139 | (signing). This attribute will be set when the result object's ``status`` attribute is 140 | set to ``invalid recipient`` and will contain more information about the failure in the 141 | form of ``reason:ident`` where ``reason`` is a text description of the reason, and 142 | ``ident`` identifies the recipient key. 143 | 144 | * Add ``scan_keys_mem()`` function to scan keys in a string. Thanks to Sky Moore 145 | for the patch. 146 | 147 | * Fix #214: Handle multiple signatures when one of them is invalid or unverified. 148 | 149 | * A ``problems`` attribute was added which holds problems reported by ``gpg`` 150 | during verification. This is a list of dictionaries, one for each reported 151 | problem. Each dictionary will have ``status`` and ``keyid`` keys indicating 152 | the problem and the corresponding key; other information in the dictionaries 153 | will be error specific. 154 | 155 | * Fix #217: Use machine-readable interface to query the ``gpg`` version. Thanks to Justus 156 | Winter for the patch. 157 | 158 | * Added the ability to export keys to a file. Thanks to Leif Liddy for the patch. 159 | 160 | 161 | 0.5.0 162 | ----- 163 | 164 | Released: 2022-08-23 165 | 166 | * Fixed #181: Added the ability to pass file paths to encrypt_file, decrypt_file, 167 | sign_file, verify_file, get_recipients_file and added import_keys_file. 168 | 169 | * Fixed #183: Handle FAILURE and UNEXPECTED conditions correctly. Thanks to sebbASF for 170 | the patch. 171 | 172 | * Fixed #185: Handle VALIDSIG arguments more robustly. 173 | 174 | * Fixed #188: Remove handling of DECRYPTION_FAILED from Verify code, as not required 175 | there. Thanks to sebbASF for the patch. 176 | 177 | * Fixed #190: Handle KEY_CREATED more robustly. 178 | 179 | * Fixed #191: Handle NODATA messages during verification. 180 | 181 | * Fixed #196: Don't log chunk data by default, as it could contain sensitive 182 | information (during decryption, for example). 183 | 184 | * Added the ability to pass an environment to the gpg executable. Thanks to Edvard 185 | Rejthar for the patch. 186 | 187 | 188 | 0.4.9 189 | ----- 190 | 191 | Released: 2022-05-20 192 | 193 | * Fixed #161: Added a status attribute to the returned object from gen_key() which 194 | is set to 'ok' if a key was successfully created, or 'key not created' if that 195 | was reported by gpg, or None in any other case. 196 | 197 | * Fixed #164: Provided the ability to add subkeys. Thanks to Daniel Kilimnik for the 198 | feature request and patch. 199 | 200 | * Fixed #166: Added keygrip values to the information collected when keys are listed. 201 | Thanks to Daniel Kilimnik for the feature request and patch. 202 | 203 | * Fixed #173: Added extra_args to send_keys(), recv_keys() and search_keys() to allow 204 | passing options relating to key servers. 205 | 206 | 0.4.8 207 | ----- 208 | 209 | Released: 2021-11-24 210 | 211 | * Fixed #147: Return gpg's return code in all result instances. 212 | 213 | * Fixed #152: Add check for invalid file objects. 214 | 215 | * Fixed #157: Provide more useful status message when a secret key is absent. 216 | 217 | * Fixed #158: Added a get_recipients() API to find the recipients of an encrypted 218 | message without decrypting it. 219 | 220 | 221 | 0.4.7 222 | ----- 223 | 224 | Released: 2021-03-11 225 | 226 | * Fixed #129, #141: Added support for no passphrase during key generation. 227 | 228 | * Fixed #143: Improved permission-denied test. Thanks to Elliot Cameron for the patch. 229 | 230 | * Fixed #144: Updated logging to only show partial results. 231 | 232 | * Fixed #146: Allowed a passphrase to be passed to import_keys(). Thanks to Chris de 233 | Graaf for the patch. 234 | 235 | 236 | 0.4.6 237 | ----- 238 | 239 | Released: 2020-04-17 240 | 241 | * Fixed #122: Updated documentation about gnupghome needing to be an existing 242 | directory. 243 | 244 | * Fixed #123: Handled error conditions from gpg when calling trust_keys(). 245 | 246 | * Fixed #124: Avoided an exception being raised when ImportResult.summary() 247 | was called after a failed recv_keys(). 248 | 249 | * Fixed #128: Added ECC support by changing key generation parameters. (The Key-Length 250 | value isn't added if a curve is specified.) 251 | 252 | * Fixed #130: Provided a mechanism to provide more complete error messages. 253 | 254 | Support for Python versions 3.5 and under is discontinued, except for Python 2.7. 255 | 256 | 257 | 0.4.5 258 | ----- 259 | 260 | Released: 2019-08-12 261 | 262 | * Fixed #107: Improved documentation. 263 | 264 | * Fixed #112: Raised a ValueError if a gnupghome is specified which is not an 265 | existing directory. 266 | 267 | * Fixed #113: Corrected stale link in the documentation. 268 | 269 | * Fixed #116: Updated documentation to clarify when spurious key-expired/ 270 | signature-expired messages might be seen. 271 | 272 | * Fixed #119: Added --yes to avoid pinentry when deleting secret keys with 273 | GnuPG >= 2.1. 274 | 275 | * A warning is logged if gpg returns a non-zero return code. 276 | 277 | * Added ``extra_args`` to ``import_keys``. 278 | 279 | * Added support for CI using AppVeyor. 280 | 281 | 282 | 0.4.4 283 | ----- 284 | 285 | Released: 2019-01-24 286 | 287 | * Fixed #108: Changed how any return value from the ``on_data`` callable is 288 | processed. In earlier versions, the return value was ignored. In this version, 289 | if the return value is ``False``, the data received from ``gpg`` is not 290 | buffered. Otherwise (if the value is ``None`` or ``True``, for example), the 291 | data is buffered as normal. This functionality can be used to do your own 292 | buffering, or to prevent buffering altogether. 293 | 294 | The ``on_data`` callable is also called once with an empty byte-string to 295 | signal the end of data from ``gpg``. 296 | 297 | * Fixed #97: Added an additional attribute ``check_fingerprint_collisions`` to 298 | ``GPG`` instances, which defaults to ``False``. It seems that ``gpg`` is happy 299 | to have duplicate keys and fingerprints in a keyring, so we can't be too 300 | strict. A user can set this attribute of an instance to ``True`` to trigger a 301 | check for collisions. 302 | 303 | * Fixed #111: With GnuPG 2.2.7 or later, provide the fingerprint of a signing 304 | key for a failed signature verification, if available. 305 | 306 | * Fixed #21: For verification where multiple signatures are involved, a 307 | mapping of signature_ids to fingerprint, keyid, username, creation date, 308 | creation timestamp and expiry timestamp is provided. 309 | 310 | * Added a check to disallow certain control characters ('\r', '\n', NUL) in 311 | passphrases. 312 | 313 | 314 | 0.4.3 315 | ----- 316 | 317 | Released: 2018-06-13 318 | 319 | * Added --no-verbose to the gpg command line, in case verbose is specified in 320 | gpg.conf - we don't need verbose output. 321 | 322 | 323 | 0.4.2 324 | ----- 325 | 326 | Released: 2018-03-28 327 | 328 | * Fixed #81: Subkey information is now collected and returned in a ``subkey_info`` 329 | dictionary keyed by the subkey's ID. 330 | 331 | * Fixed #84: GPG2 version is now correctly detected on OS X. 332 | 333 | * Fixed #94: Added ``expect_passphrase`` password for use on GnuPG >= 2.1 when 334 | passing passphrase to ``gpg`` via pinentry. 335 | 336 | * Fixed #95: Provided a ``trust_keys`` method to allow setting the trust level 337 | for keys. Thanks to William Foster for a suggested implementation. 338 | 339 | * Made the exception message when the gpg executable is not found contain the 340 | path of the executable that was tried. Thanks to Kostis Anagnostopoulos for 341 | the suggestion. 342 | 343 | * Fixed #100: Made the error message less categorical in the case of a failure 344 | with an unspecified reason, adding some information from gpg error codes when 345 | available. 346 | 347 | 348 | 0.4.1 349 | ----- 350 | 351 | Released: 2017-07-06 352 | 353 | * Updated message handling logic to no longer raise exceptions when a message 354 | isn't recognised. Thanks to Daniel Kahn Gillmor for the patch. 355 | 356 | * Always use always use ``--fixed-list-mode``, ``--batch`` and 357 | ``--with-colons``. Thanks to Daniel Kahn Gillmor for the patch. 358 | 359 | * Improved ``scan_keys()`` handling on GnuPG >= 2.1. Thanks to Daniel Kahn 360 | Gillmor for the patch. 361 | 362 | * Improved test behaviour with GnuPG >= 2.1. Failures when deleting test 363 | directory trees are now ignored. Thanks to Daniel Kahn Gillmor for the patch. 364 | 365 | * Added ``close_file`` keyword argument to verify_file to allow the file closing 366 | to be made optional. Current behaviour is maintained - ``close_file=False`` 367 | can be passed to skip closing the file being verified. 368 | 369 | * Added the ``extra_args`` keyword parameter to allow custom arguments to be 370 | passed to the ``gpg`` executable. 371 | 372 | * Instances of the ``GPG`` class now have an additional ``on_data`` attribute, 373 | which defaults to ``None``. It can be set to a callable which will be called 374 | with a single argument - a binary chunk of data received from the ``gpg`` 375 | executable. The callable can do whatever it likes with the chunks passed to it 376 | - e.g. write them to a separate stream. The callable should not raise any 377 | exceptions (unless it wants the current operation to fail). 378 | 379 | 380 | 0.4.0 381 | ----- 382 | 383 | Released: 2017-01-29 384 | 385 | * Added support for ``KEY_CONSIDERED`` in more places - encryption / 386 | decryption, signing, key generation and key import. 387 | 388 | * Partial fix for #32 (GPG 2.1 compatibility). Unfortunately, better 389 | support cannot be provided at this point, unless there are certain 390 | changes (relating to pinentry popups) in how GPG 2.1 works. 391 | 392 | * Fixed #60: An IndexError was being thrown by ``scan_keys()``. 393 | 394 | * Ensured that utf-8 encoding is used when the ``--with-column`` mode is 395 | used. Thanks to Yann Leboulanger for the patch. 396 | 397 | * ``list_keys()`` now uses ``--fixed-list-mode``. Thanks to Werner Koch 398 | for the pointer. 399 | 400 | 401 | 0.3.9 402 | ----- 403 | 404 | Released: 2016-09-10 405 | 406 | * Fixed #38: You can now request information about signatures against 407 | keys. Thanks to SunDwarf for the suggestion and patch, which was used 408 | as a basis for this change. 409 | 410 | * Fixed #49: When exporting keys, no attempt is made to decode the output when 411 | armor=False is specified. 412 | 413 | * Fixed #53: A ``FAILURE`` message caused by passing an incorrect passphrase 414 | is handled. 415 | 416 | * Handled ``EXPORTED`` and ``EXPORT_RES`` messages while exporting keys. Thanks 417 | to Marcel Pörner for the patch. 418 | 419 | * Fixed #54: Improved error message shown when gpg is not available. 420 | 421 | * Fixed #55: Added support for ``KEY_CONSIDERED`` while verifying. 422 | 423 | * Avoided encoding problems with filenames under Windows. Thanks to Kévin 424 | Bernard-Allies for the patch. 425 | 426 | * Fixed #57: Used a better mechanism for comparing keys. 427 | 428 | 429 | 0.3.8 430 | ----- 431 | 432 | Released: 2015-09-24 433 | 434 | * Fixed #22: handled ``PROGRESS`` messages during verification and signing. 435 | 436 | * Fixed #26: handled ``PINENTRY_LAUNCHED`` messages during verification, 437 | decryption and key generation. 438 | 439 | * Fixed #28: Allowed a default Name-Email to be computed even when neither of 440 | ``LOGNAME`` and ``USERNAME`` are in the environment. 441 | 442 | * Fixed #29: Included test files missing from the tarball in previous versions. 443 | 444 | * Fixed #39: On Python 3.x, passing a text instead of a binary stream caused 445 | file decryption to hang due to a ``UnicodeDecodeError``. This has now been 446 | correctly handled: The decryption fails with a "no data" status. 447 | 448 | * Fixed #41: Handled Unicode filenames correctly by encoding them on 2.x using 449 | the file system encoding. 450 | 451 | * Fixed #43: handled ``PINENTRY_LAUNCHED`` messages during key export. Thanks 452 | to Ian Denhardt for looking into this. 453 | 454 | * Hide the console window which appears on Windows when gpg is spawned. 455 | Thanks to Kévin Bernard-Allies for the patch. 456 | 457 | * Subkey fingerprints are now captured. 458 | 459 | * The returned value from the ``list_keys`` method now has a new attribute, 460 | ``key_map``, which is a dictionary mapping key and subkey fingerprints to 461 | the corresponding key's dictionary. With this change, you don't need to 462 | iterate over the (potentially large) returned list to search for a key with 463 | a given fingerprint - the ``key_map`` dict will take you straight to the key 464 | info, whether the fingerprint you have is for a key or a subkey. Thanks to 465 | Nick Daly for the initial suggestion. 466 | 467 | 0.3.7 468 | ----- 469 | 470 | Released: 2014-12-07 471 | 472 | Signed with PGP key: Vinay Sajip (CODE SIGNING KEY) 473 | 474 | Key Fingerprint : CA74 9061 914E AC13 8E66 EADB 9147 B477 339A 9B86 475 | 476 | * Added an ``output`` keyword parameter to the ``sign`` and 477 | ``sign_file`` methods, to allow writing the signature to a file. 478 | Thanks to Jannis Leidel for the patch. 479 | 480 | * Allowed specifying ``True`` for the ``sign`` keyword parameter, 481 | which allows use of the default key for signing and avoids having to 482 | specify a key id when it's desired to use the default. Thanks to 483 | Fabian Beutel for the patch. 484 | 485 | * Used a uniform approach with subprocess on Windows and POSIX: shell=True 486 | is not used on either. 487 | 488 | * When signing/verifying, the status is updated to reflect any expired or 489 | revoked keys or signatures. 490 | 491 | * Handled 'NOTATION_NAME' and 'NOTATION_DATA' during verification. 492 | 493 | * Fixed #1, #16, #18, #20: Quoting approach changed, since now shell=False. 494 | 495 | * Fixed #14: Handled 'NEED_PASSPHRASE_PIN' message. 496 | 497 | * Fixed #8: Added a scan_keys method to allow scanning of keys without the 498 | need to import into a keyring. Thanks to Venzen Khaosan for the suggestion. 499 | 500 | * Fixed #5: Added '0x' prefix when searching for keys. Thanks to Aaron Toponce 501 | for the report. 502 | 503 | * Fixed #4: Handled 'PROGRESS' message during encryption. Thanks to Daniel 504 | Mills for the report. 505 | 506 | * Fixed #3: Changed default encoding to Latin-1. 507 | 508 | * Fixed #2: Raised ValueError if no recipients were specified 509 | for an asymmetric encryption request. 510 | 511 | * Handled 'UNEXPECTED' message during verification. Thanks to 512 | David Andersen for the patch. 513 | 514 | * Replaced old range(len(X)) idiom with enumerate(). 515 | 516 | * Refactored ``ListKeys`` / ``SearchKeys`` classes to maximise use of common 517 | functions. 518 | 519 | * Fixed GC94: Added ``export-minimal`` and ``armor`` options when exporting 520 | keys. This addition was inadvertently left out of 0.3.6. 521 | 522 | 0.3.6 523 | ----- 524 | 525 | Released: 2014-02-05 526 | 527 | * Fixed GC82: Enabled fast random tests on gpg as well as gpg2. 528 | * Fixed GC85: Avoided deleting temporary file to preserve its permissions. 529 | * Fixed GC87: Avoided writing passphrase to log. 530 | * Fixed GC95: Added ``verify_data()`` method to allow verification of 531 | signatures in memory. 532 | * Fixed GC96: Regularised end-of-line characters. 533 | * Fixed GC98: Rectified problems with earlier fix for shell injection. 534 | 535 | 0.3.5 536 | ----- 537 | 538 | Released: 2013-08-30 539 | 540 | * Added improved shell quoting to guard against shell injection. 541 | * Fixed GC76: Added ``search_keys()`` and ``send_keys()`` methods. 542 | * Fixed GC77: Allowed specifying a symmetric cipher algorithm. 543 | * Fixed GC78: Fell back to utf-8 encoding when no other could be determined. 544 | * Fixed GC79: Default key length is now 2048 bits. 545 | * Fixed GC80: Removed the Name-Comment default in key generation. 546 | 547 | 0.3.4 548 | ----- 549 | 550 | Released: 2013-06-05 551 | 552 | * Fixed GC65: Fixed encoding exception when getting version. 553 | * Fixed GC66: Now accepts sets and frozensets where appropriate. 554 | * Fixed GC67: Hash algorithm now captured in sign result. 555 | * Fixed GC68: Added support for ``--secret-keyring``. 556 | * Fixed GC70: Added support for multiple keyrings. 557 | 558 | 0.3.3 559 | ----- 560 | 561 | Released: 2013-03-11 562 | 563 | * Fixed GC57: Handled control characters in ``list_keys()``. 564 | * Fixed GC61: Enabled fast random for testing. 565 | * Fixed GC62: Handled ``KEYEXPIRED`` status. 566 | * Fixed GC63: Handled ``NO_SGNR`` status. 567 | 568 | 0.3.2 569 | ----- 570 | 571 | Released: 2013-01-17 572 | 573 | * Fixed GC56: Disallowed blank values in key generation. 574 | * Fixed GC57: Handled colons and other characters in ``list_keys()``. 575 | * Fixed GC59/GC60: Handled ``INV_SGNR`` status during verification and removed 576 | calls requiring interactive password input from doctests. 577 | 578 | 0.3.1 579 | ----- 580 | 581 | Released: 2012-09-01 582 | 583 | * Fixed GC45: Allowed additional arguments to gpg executable. 584 | * Fixed GC50: Used latin-1 encoding in tests when it's known to be required. 585 | * Fixed GC51: Test now returns non-zero exit status on test failure. 586 | * Fixed GC53: Now handles ``INV_SGNR`` and ``KEY_NOT_CREATED`` statuses. 587 | * Fixed GC55: Verification and decryption now return trust level of signer in 588 | integer and text form. 589 | 590 | 0.3.0 591 | ----- 592 | 593 | Released: 2012-05-12 594 | 595 | * Fixed GC49: Reinstated Yann Leboulanger's change to support subkeys 596 | (accidentally left out in 0.2.7). 597 | 598 | 0.2.9 599 | ----- 600 | 601 | Released: 2012-03-29 602 | 603 | * Fixed GC36: Now handles ``CARDCTRL`` and ``POLICY_URL`` messages. 604 | * Fixed GC40: Now handles ``DECRYPTION_INFO``, ``DECRYPTION_FAILED`` and 605 | ``DECRYPTION_OKAY`` messages. 606 | * The ``random_binary_data file`` is no longer shipped, but constructed by the 607 | test suite if needed. 608 | 609 | 0.2.8 610 | ----- 611 | 612 | Released: 2011-09-02 613 | 614 | * Fixed GC29: Now handles ``IMPORT_RES`` while verifying. 615 | * Fixed GC30: Fixed an encoding problem. 616 | * Fixed GC33: Quoted arguments for added safety. 617 | 618 | 0.2.7 619 | ----- 620 | 621 | Released: 2011-04-10 622 | 623 | * Fixed GC24: License is clarified as BSD. 624 | * Fixed GC25: Incorporated Daniel Folkinshteyn's changes. 625 | * Fixed GC26: Incorporated Yann Leboulanger's subkey change. 626 | * Fixed GC27: Incorporated hysterix's support for symmetric encryption. 627 | * Did some internal cleanups of Unicode handling. 628 | 629 | 0.2.6 630 | ----- 631 | 632 | Released: 2011-01-25 633 | 634 | * Fixed GC14: Should be able to accept passphrases from GPG-Agent. 635 | * Fixed GC19: Should be able to create a detached signature. 636 | * Fixed GC21/GC23: Better handling of less common responses from GPG. 637 | 638 | 0.2.5 639 | ----- 640 | 641 | Released: 2010-10-13 642 | 643 | * Fixed GC11/GC16: Detached signatures can now be created. 644 | * Fixed GC3: Detached signatures can be verified. 645 | * Fixed GC12: Better support for RSA and IDEA. 646 | * Fixed GC15/GC17: Better support for non-ASCII input. 647 | 648 | 0.2.4 649 | ----- 650 | 651 | Released: 2010-03-01 652 | 653 | * Fixed GC9: Now allows encryption without armor and the ability to encrypt 654 | and decrypt directly to/from files. 655 | 656 | 0.2.3 657 | ----- 658 | 659 | Released: 2010-01-07 660 | 661 | * Fixed GC7: Made sending data to process threaded and added a test case. 662 | With a test data file used by the test case, the archive size has gone up 663 | to 5MB (the size of the test file). 664 | 665 | 0.2.2 666 | ----- 667 | 668 | Released: 2009-10-06 669 | 670 | * Fixed GC5/GC6: Added ``--batch`` when specifying ``--passphrase-fd`` and 671 | changed the name of the distribution file to add the ``python-`` prefix. 672 | 673 | 0.2.1 674 | ----- 675 | 676 | Released: 2009-08-07 677 | 678 | * Fixed GC2: Added ``handle_status()`` method to the ``ListKeys`` class. 679 | 680 | 0.2.0 681 | ----- 682 | 683 | Released: 2009-07-16 684 | 685 | * Various changes made to support Python 3.0. 686 | 687 | 0.1.0 688 | ----- 689 | 690 | Released: 2009-07-04 691 | 692 | * Initial release. 693 | -------------------------------------------------------------------------------- /docs/index.rst: -------------------------------------------------------------------------------- 1 | .. GnuPG Wrapper for Python documentation master file, created by 2 | sphinx-quickstart on Thu Jul 02 16:14:12 2009. 3 | 4 | ########################################### 5 | `python-gnupg` - A Python wrapper for GnuPG 6 | ########################################### 7 | 8 | .. rst-class:: release-info 9 | 10 | .. list-table:: 11 | :widths: auto 12 | :stub-columns: 1 13 | 14 | * - Release: 15 | - |release| 16 | * - Date: 17 | - |today| 18 | 19 | .. module:: gnupg 20 | :synopsis: A Python wrapper for the GNU Privacy Guard (GnuPG) 21 | 22 | .. moduleauthor:: Vinay Sajip 23 | .. sectionauthor:: Vinay Sajip 24 | 25 | 26 | .. toctree:: 27 | :maxdepth: 4 28 | 29 | The ``gnupg`` module allows Python programs to make use of the functionality provided 30 | by the `GNU Privacy Guard `_ (abbreviated GPG or GnuPG). Using 31 | this module, Python programs can encrypt and decrypt data, digitally sign documents 32 | and verify digital signatures, manage (generate, list and delete) encryption keys, 33 | using Public Key Infrastructure (PKI) encryption technology based on OpenPGP. 34 | 35 | This module is expected to be used with Python versions >= 3.6, or Python 2.7 for 36 | legacy code. Install this module using ``pip install python-gnupg``. You can then use 37 | this module in your own code by doing ``import gnupg`` or similar. 38 | 39 | .. _fork-note: 40 | 41 | .. note:: 42 | There is at least one fork of this project, which was apparently created because an 43 | earlier version of this software used the ``subprocess`` module with 44 | ``shell=True``, making it vulnerable to shell injection. **This is no longer the 45 | case**. 46 | 47 | Forks may not be drop-in compatible with this software, so take care to use the 48 | correct version, as indicated in the ``pip install`` command above. 49 | 50 | .. index:: Deployment 51 | 52 | .. _deployment: 53 | 54 | Deployment Requirements 55 | ======================= 56 | 57 | Apart from a recent-enough version of Python, in order to use this module you need to 58 | have access to a compatible version of the GnuPG executable. The system has been 59 | tested with GnuPG v1.4.9 on Windows and Ubuntu. On a Linux platform, this will 60 | typically be installed via your distribution's package manager (e.g. ``apt-get`` on 61 | Debian/Ubuntu). Windows binaries are available `here 62 | `_ -- use one of the ``gnupg-w32cli-1.4.x.exe`` 63 | installers for the simplest deployment options. 64 | 65 | .. note:: 66 | On Windows, it is *not* necessary to perform a full installation of GnuPG, using 67 | the standard installer, on each computer: it is normally sufficient to distribute 68 | only the executable, ``gpg.exe``, and a DLL which it depends on, ``iconv.dll``. 69 | These files do not need to be placed in system directories, nor are registry 70 | changes needed. The files need to be placed in a location such that implicit 71 | invocation will find them - such as the working directory of the application which 72 | uses the ``gnupg`` module, or on the system path if that is appropriate for your 73 | requirements. Alternatively, you can specify the full path to the ``gpg`` 74 | executable. *Note, however, that if you want to use GnuPG 2.0, then this simple 75 | deployment approach may not work, because there are more dependent files which you 76 | have to ship. For this reason, our recommendation is to stick with GnuPG 1.4.x on 77 | Windows, unless you specifically need 2.0 features - in which case, you may have to 78 | do a full installation rather than just relying on a couple of files).* 79 | 80 | Recent versions of GnuPG (>= 2.1.x) introduce a number of changes: 81 | 82 | * By default, passphrases cannot be passed via streams to ``gpg`` unless the line 83 | ``allow-loopback-pinentry`` is added to ``gpg-agent.conf`` in the home directory 84 | used by ``gpg`` (this is also where the keyring files are kept). If that file 85 | does not exist, you will need to create it with that single line. Note that even 86 | with this configuration, some versions of GnuPG 2.1.x won't work as expected. In 87 | our testing, we found, for example, that the 2.1.11 executable shipped with 88 | Ubuntu 16.04 didn't behave helpfully, whereas a GnuPG 2.1.15 executable compiled 89 | from source on the same machine worked as expected. 90 | * To export secret keys, a passphrase must be provided. 91 | 92 | .. index:: Acknowledgements 93 | 94 | Acknowledgements 95 | ================ 96 | 97 | This module is based on an earlier version, ``GPG.py``, written by Andrew Kuchling. 98 | This was further improved by Richard Jones, and then even further by Steve Traugott. 99 | The ``gnupg`` module is derived from `Steve Traugott's module 100 | `_ 101 | (the original site no longer exists - this link is to the Wayback Machine), and uses 102 | Python's ``subprocess`` module to communicate with the GnuPG executable, which it uses 103 | to spawn a subprocess to do the real work. 104 | 105 | I've gratefully incorporated improvements contributed or suggested by: 106 | 107 | * Paul Cunnane (detached signature support) 108 | * Daniel Folkinshteyn (``recv_keys``, handling of subkeys and SIGEXPIRED, KEYEXPIRED 109 | while verifying, EXPKEYSIG, REVKEYSIG) 110 | * Dmitry Gladkov (handle KEYEXPIRED when importing) 111 | * Abdul Karim (keyring patch) 112 | * Yann Leboulanger (handle ERRSIG and NO_PUBKEY while verifying, get subkeys) 113 | * Kirill Yakovenko (RSA and IDEA support) 114 | * Robert Leftwich (handle INV_SGNR, KEY_NOT_CREATED) 115 | * Michal Niklas (Trust levels for signature verification) 116 | * David Noël (``search_keys``, ``send_keys`` functionality) 117 | * David Andersen (handle UNEXPECTED during verification) 118 | * Jannis Leidel (output signature to a file) 119 | * Venzen Khaosan (scan_keys functionality) 120 | * Marcel Pörner (handle EXPORTED, EXPORT_RES) 121 | * Kévin Bernard-Allies (handle filename encoding under Windows) 122 | * Daniel Kahn Gillmor (various improvements which were released in 0.4.1) 123 | * William Foster (trust_key patch) 124 | 125 | and Google Code / BitBucket users 126 | 127 | * dprovins (ListKeys handle_status) 128 | * ernest0x (improved support for non-ASCII input) 129 | * eyepulp (additional options for encryption/decryption) 130 | * hysterix.is.slackin (symmetric encryption support) 131 | * natureshadow (improved status handling when smart cards in use) 132 | * SunDwarf (storing signatures against keys) 133 | 134 | (If I've missed anyone from this list, please let me know.) 135 | 136 | 137 | Before you Start 138 | ================ 139 | 140 | GnuPG works on the basis of a "home directory" which is used to store public and 141 | private keyring files as well as a trust database. You need to identify in advance 142 | which directory on the end-user system will be used as the home directory, as you will 143 | need to pass this information to ``gnupg``. 144 | 145 | .. index:: Getting started 146 | 147 | Getting Started 148 | =============== 149 | 150 | You interface to the GnuPG functionality through an instance of the ``GPG`` class:: 151 | 152 | >>> gpg = gnupg.GPG(gnupghome='/path/to/home/directory') 153 | 154 | If the home directory does not exist, a ValueError will be raised. Thereafter, all the 155 | operations available are accessed via methods of this instance. If the ``gnupghome`` 156 | parameter is omitted, GnuPG will use whatever directory is the default (consult the 157 | GnuPG documentation for more information on what this might be). 158 | 159 | The :class:`GPG` constructor also accepts the following additional optional keyword 160 | arguments: 161 | 162 | gpgbinary (defaults to "gpg") 163 | The path to the ``gpg`` executable. 164 | verbose (defaults to ``False``) 165 | Print information (e.g. the gpg command lines, and status messages returned by 166 | gpg) to the console. You don't generally need to set this option, since the module 167 | uses Python's ``logging`` package to provide more flexible functionality. The 168 | status messages from ``gpg`` are quite voluminous, especially during key generation. 169 | use_agent (defaults to ``False``) 170 | If specified as True, the ``--use-agent`` parameter is passed to ``gpg``, asking it to 171 | use any in-memory GPG agent (which remembers your credentials). 172 | keyring (defaults to ``None``) 173 | If specified, the value is used as the name of the keyring file. The default 174 | keyring is not used. A list of paths to keyring files can also be specified. 175 | options (defaults to ``None``) 176 | If specified, the value should be a list of additional command-line options to 177 | pass to ``gpg``. 178 | secret_keyring (defaults to ``None``) 179 | If specified, the value is used as the name of the secret keyring file. A list of 180 | paths to secret keyring files can also be specified. *Note that these files are 181 | not used by GnuPG >= 2.1.* 182 | env (defaults to ``None``) 183 | If specified, the value is used as the environment variables used when calling the GPG 184 | executable. 185 | 186 | .. versionchanged:: 0.3.4 187 | The ``keyring`` argument can now also be a list of keyring filenames. 188 | 189 | .. versionadded:: 0.3.4 190 | The ``secret_keyring`` argument was added. *Note that this argument is not used 191 | when working with GnuPG >= 2.1.* 192 | 193 | .. note:: If you specify values in ``options``, make sure you don't specify values 194 | which will conflict with other values added by ``python-gnupg``. You should be familiar 195 | with GPG command-line arguments and how they affect GPG's operation. 196 | 197 | .. versionchanged:: 0.3.7 198 | The default encoding was changed to ``latin-1``. In earlier versions, it was either 199 | ``locale.getpreferredencoding()`` or, failing that, ``sys.stdin.encoding``, and 200 | failing that, ``utf-8``. 201 | 202 | .. versionadded:: 0.5.0 203 | The ``env`` argument was added. 204 | 205 | If the ``gpgbinary`` executable cannot be found, a ``ValueError`` is raised in 206 | :meth:`GPG.__init__`. 207 | 208 | The low-level communication between the ``gpg`` executable and ``python-gnupg`` is in 209 | terms of bytes, and ``python-gnupg`` tries to convert gpg's ``stderr`` stream to text 210 | using an encoding. The default value of this is ``latin-1``, but you can override this 211 | by setting the encoding name in the GPG instance's ``encoding`` attribute after 212 | instantiation, like this:: 213 | 214 | >>> gpg = gnupg.GPG(gnupghome='/path/to/home/directory') 215 | >>> gpg.encoding = 'utf-8' 216 | 217 | .. note:: If you use the wrong encoding, you may get exceptions. The ``'latin-1'`` 218 | encoding leaves bytes as-is and shouldn't fail with encoding/decoding errors, 219 | though it may not decode text correctly (so you may see odd characters in the 220 | decoding output). The ``gpg`` executable will use an output encoding based on your 221 | environment settings (e.g. environment variables, code page etc.) but defaults to 222 | latin-1. 223 | 224 | From version 0.5.2 onwards, you can also control the buffer size for the I/O between 225 | ``gpg`` and ``python-gnupg`` by setting the ``buffer_size`` attribute on a GPG instance. 226 | It defaults to 16K. 227 | 228 | .. versionadded:: 0.5.2 229 | The ``buffer_size`` attribute was added. 230 | 231 | 232 | .. index:: Key; management 233 | 234 | Key Management 235 | ============== 236 | 237 | The module provides functionality for generating (creating) keys, listing keys, 238 | deleting keys, and importing and exporting keys. 239 | 240 | .. index:: Key; generating 241 | 242 | Generating keys 243 | --------------- 244 | 245 | The first thing you typically want to do when starting with a PKI framework is to 246 | generate some keys. You can do this using the :meth:`~gnupg.GPG.gen_key` method:: 247 | 248 | >>> key = gpg.gen_key(input_data) 249 | 250 | where ``input_data`` is a special command string which tells GnuPG the 251 | parameters you want to use when creating the key. To make life easier, a helper 252 | method :meth:`~gnupg.GPG.gen_key_input` is provided which takes keyword 253 | arguments which allow you to specify individual parameters of the key, as in 254 | the following example:: 255 | 256 | >>> input_data = gpg.gen_key_input(key_type="RSA", key_length=1024) 257 | 258 | Sensible defaults are provided for parameters which you don't specify, as shown in the 259 | following table. 260 | 261 | .. cssclass:: generic-table table-bordered table-responsive-sm table-striped mx-auto mb-3 colwidths-auto smaller hpad 262 | 263 | +---------------+------------------+-------------------------+-----------------------------+---------------------------------------------+ 264 | | Parameter | Keyword Argument | Default value | Example values | Meaning of parameter | 265 | +===============+==================+=========================+=============================+=============================================+ 266 | | Key-Type | key_type | "RSA" | "RSA", "DSA" | The type of the primary key to generate. It | 267 | | | | | | must be capable of signing. | 268 | +---------------+------------------+-------------------------+-----------------------------+---------------------------------------------+ 269 | | Key-Length | key_length | 1024 | 1024, 2048 | The length of the primary key in bits. | 270 | +---------------+------------------+-------------------------+-----------------------------+---------------------------------------------+ 271 | | Name-Real | name_real | "Autogenerated Key" | "Fred Bloggs" | The real name of the user identity which | 272 | | | | | | is represented by the key. | 273 | +---------------+------------------+-------------------------+-----------------------------+---------------------------------------------+ 274 | | Name-Comment | name_comment | "Generated by gnupg.py" | "A test user" | A comment to attach to the user id. | 275 | +---------------+------------------+-------------------------+-----------------------------+---------------------------------------------+ 276 | | Name-Email | name_email | @ | "fred.bloggs\@domain.com" | An email address for the user. | 277 | +---------------+------------------+-------------------------+-----------------------------+---------------------------------------------+ 278 | 279 | If you don't specify any parameters, the values in the table above will be used with 280 | the defaults indicated. There is a whole set of other parameters you can specify; see 281 | `this GnuPG document `_ for more 282 | details. While use of RSA keys is common (they can be used for both signing and 283 | encryption), another popular option is to use a DSA primary key (for signing) together 284 | with a secondary El-Gamal key (for encryption). For this latter option, you could 285 | supply the following additional parameters: 286 | 287 | .. cssclass:: generic-table table-bordered table-responsive-sm table-striped mx-auto mb-3 colwidths-auto smaller hpad 288 | 289 | +---------------+------------------+--------------------------------+---------------------------------------------+ 290 | | Parameter | Keyword Argument | Example values | Meaning of parameter | 291 | +===============+==================+================================+=============================================+ 292 | | Subkey-Type | subkey_type | "RSA", "ELG-E" | The type of the secondary key to generate. | 293 | +---------------+------------------+--------------------------------+---------------------------------------------+ 294 | | Subkey-Length | subkey_length | 1024, 2048 | The length of the secondary key in bits. | 295 | +---------------+------------------+--------------------------------+---------------------------------------------+ 296 | | Expire-Date | expire_date | "2009-12-31", "365d", "3m", | The expiration date for the primary and any | 297 | | | | "6w", "5y", "seconds=", | secondary key. You can specify an ISO date, | 298 | | | | 0 | A number of days/weeks/months/years, an | 299 | | | | | epoch value, or 0 for a non-expiring key. | 300 | +---------------+------------------+--------------------------------+---------------------------------------------+ 301 | | Passphrase | passphrase | "secret" | The passphrase to use. If this parameter is | 302 | | | | | not specified, no passphrase is needed to | 303 | | | | | access the key. *Passphrases using newlines | 304 | | | | | are not supported*. **Note that for GnuPG | 305 | | | | | versions >= 2.1, a passphrase must be | 306 | | | | | provided, unless extra steps are taken**: | 307 | | | | | see the ``no_protection`` argument, below. | 308 | +---------------+------------------+--------------------------------+---------------------------------------------+ 309 | | %no-protection| no_protection | False (the default), True | If no passphrase is wanted for a key (which | 310 | | | | | might be the default for tests, say), or if | 311 | | | | | you want to use an empty string as a | 312 | | | | | passphrase, then you should specify ``True``| 313 | | | | | for this parameter. Otherwise, and if you | 314 | | | | | don't use pinentry to enter a passphrase, | 315 | | | | | then GnuPG >= 2.1 will not allow this. It | 316 | | | | | doesn't make sense to specify ``True`` if a | 317 | | | | | non-empty passphrase is being supplied. | 318 | +---------------+------------------+--------------------------------+---------------------------------------------+ 319 | 320 | A complete list of key generation parameters can be found in the GnuPG documentation 321 | `here `__. 322 | 323 | .. versionadded:: 0.4.7 324 | The ``no_protection`` keyword argument was added. 325 | 326 | Whatever keyword arguments you pass to :meth:`~gnupg.GPG.gen_key_input` (other 327 | than ``no_protection``) will be converted to the parameters expected by GnuPG 328 | by replacing underscores with hyphens and title-casing the result. You can of 329 | course construct the parameters in your own dictionary ``params`` and then pass 330 | it as follows:: 331 | 332 | >>> input_data = gpg.gen_key_input(**params) 333 | 334 | 335 | The ``no_protection`` argument, if `True`, will be used to generate a 336 | `%no-protection` line which tells GnuPG that no protection with a 337 | passphrase is desired. 338 | 339 | The return value from :meth:`~gnupg.GPG.gen_key` is an object whose 340 | `type` and `fingerprint` attributes indicate the type and fingerprint of the 341 | created key. If no key was created, these will be `None`. 342 | 343 | .. versionadded:: 0.4.9 344 | There is now also a `status` attribute to the returned object which will be `'ok'` 345 | if a key was created, `'key not created'` if that was reported by `gpg`, or `None` 346 | in other cases. 347 | 348 | .. index:: 349 | single: Key; Generating subkeys 350 | 351 | Generating subkeys 352 | ^^^^^^^^^^^^^^^^^^ 353 | 354 | To generate a subkey for an already generated key use the 355 | :meth:`~gnupg.GPG.add_subkey` method:: 356 | 357 | >>> subkey = gpg.add_subkey(master_key) # same as gpg.add_subkey(master_key, None) 358 | >>> subkey = gpg.add_subkey(master_key, master_key_password) 359 | 360 | The :meth:`~gnupg.GPG.add_subkey` method has some additional keyword 361 | arguments: 362 | 363 | * ``algorithm`` (defaulting to ``rsa``) 364 | * ``usage`` (defaulting to ``encrypt``) 365 | * ``expire`` (defaulting to ``-``) 366 | 367 | The parameters are explained with every possible value in `this GnuPG documentation 368 | `_ 369 | under ``quick-add-key``. 370 | 371 | If you use the default algorithm, you'll get the default key size, which is dependent 372 | upon the version of GnuPG that's used. If you want to specify the key size explicitly, 373 | you can use values for ``algorithm`` incorporating both the algorithm itself and the 374 | key size, as in the following examples. 375 | 376 | .. code-block:: python 377 | 378 | gpg.add_subkey(..., algorithm='rsa2048') 379 | gpg.add_subkey(..., algorithm='rsa3072') 380 | gpg.add_subkey(..., algorithm='rsa4096') 381 | 382 | 383 | .. versionadded:: 0.4.9 384 | The ``add_subkey`` method was added. 385 | 386 | Specifying key usages 387 | ^^^^^^^^^^^^^^^^^^^^^ 388 | 389 | Keys can be used for some or all of encryption, signing or authentication. 390 | These usages map onto flags assigned to a key - one or more of 'encrypt', 391 | 'sign' and 'auth'. By default, nothing is specified, which assigns all flags to 392 | a key. But sometimes you may want to depart from this behaviour. For example, 393 | if you create a subkey for encryption, then you probably don't want encryption 394 | to be enabled for the master key. You can specify the flags associated with a 395 | key by passing a ``key_usage`` keyword argument to 396 | :meth:`~gnupg.GPG.gen_key_input` which provides one or more of the above flags 397 | in a space or comma-separated string, as in these example: 398 | 399 | .. code-block:: python 400 | 401 | gpg.gen_key_input(..., key_usage='sign') 402 | gpg.gen_key_input(..., key_usage='sign encrypt') 403 | gpg.gen_key_input(..., key_usage='sign, auth') 404 | 405 | This corresponds to the ``usage`` parameter of :meth:`~gnupg.GPG.add_subkey`, 406 | described earlier. Note that you still need to ensure that the key type of the 407 | key being created is appropriate for the usages. 408 | 409 | .. index:: 410 | single: Key; elliptic curves 411 | single: ECC keys 412 | 413 | Generating elliptic curve keys 414 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 415 | 416 | To generate keys with elliptic curves, pass a `key_curve` keyword parameter to 417 | :meth:`~gnupg.GPG.gen_key_input` and omit `key_length`. For example, 418 | `key_curve='cv25519'` or `key_type='ECDSA', key_curve='nistp384'`. Refer to 419 | `GnuPG resources `_ to see which options are 420 | supported. Note that you'll need GnuPG >= 2.1 for this to work. 421 | 422 | Supplemental information on the aliases used for key types and curves is given 423 | `here 424 | `__. 425 | You can use the curve type alias in the ``algorithm`` argument to 426 | :meth:`~gnupg.GPG.add_subkey`, as in the following example. 427 | 428 | .. code-block:: python 429 | 430 | input_data = gpg.gen_key_input(key_type='EDDSA', key_curve='ed25519' ...) 431 | master_key = gpg.gen_key(input_data) 432 | subkey = gpg.add_subkey(master_key.fingerprint, algorithm='cv25519' ...) 433 | 434 | .. index:: 435 | single: Key; performance issues 436 | single: Entropy 437 | 438 | Performance Issues 439 | ^^^^^^^^^^^^^^^^^^ 440 | 441 | Key generation requires the system to work with a source of random numbers. Systems 442 | which are better at generating random numbers than others are said to have higher 443 | *entropy*. This is typically obtained from the system hardware; the GnuPG 444 | documentation recommends that keys be generated *only* on a local machine (i.e. not 445 | one being accessed across a network), and that keyboard, mouse and disk activity be 446 | maximised during key generation to increase the entropy of the system. 447 | 448 | Unfortunately, there are some scenarios - for example, on virtual machines which don't 449 | have real hardware - where insufficient entropy causes key generation to be 450 | *extremely* slow. If you come across this problem, you should investigate means of 451 | increasing the system entropy. On virtualised Linux systems, this can often be 452 | achieved by installing the ``rng-tools`` package. This is available at least on 453 | RPM-based and APT-based systems (Red Hat/Fedora, Debian, Ubuntu and derivative 454 | distributions). 455 | 456 | .. index:: Key; exporting 457 | 458 | Exporting keys 459 | -------------- 460 | 461 | To export keys, use the :meth:`~gnupg.GPG.export_keys` method:: 462 | 463 | >>> ascii_armored_public_keys = gpg.export_keys(keyids) # same as gpg.export_keys(keyids, False) 464 | >>> ascii_armored_private_keys = gpg.export_keys(keyids, True) # True => private keys 465 | 466 | For the ``keyids`` parameter, you can use a sequence of anything which GnuPG itself 467 | accepts to identify a key - for example, the keyid or the fingerprint could be used. 468 | If you want to pass a single keyid, then you can just pass in a string which 469 | identifies the key. If you pass an empty list in ``keyids``, all keys are exported. 470 | 471 | The :meth:`~gnupg.GPG.export_keys` method has some additional keyword arguments: 472 | 473 | * ``armor`` (defaulting to ``True``) - when ``True``, passes ``--armor`` to ``gpg``. 474 | * ``minimal`` (defaulting to ``False``) - when ``True``, passes 475 | ``--export-options export-minimal`` to ``gpg``. 476 | * ``passphrase`` - if specified, sends the specified passphrase to ``gpg``. For 477 | GnuPG >= 2.1, exporting secret keys requires a passphrase to be provided. 478 | * ``expect_passphrase`` - defaults to ``True`` for backward compatibility. If the 479 | passphrase is to be passed to ``gpg`` via pinentry, you wouldn't pass it here - so 480 | specify ``expect_passphrase=False`` in that case. If you don't do that, and don't 481 | pass a passphrase, a ``ValueError`` will be raised. 482 | * ``output`` - defaults to ``None``, but if specified, should be the pathname of a file 483 | to which the exported keys should be written. 484 | 485 | .. versionadded:: 0.3.7 486 | The ``armor`` and ``minimal`` keyword arguments were added. 487 | 488 | .. versionadded:: 0.4.0 489 | The ``passphrase`` keyword argument was added. 490 | 491 | .. versionadded:: 0.4.2 492 | The ``expect_passphrase`` keyword argument was added. 493 | 494 | .. versionadded:: 0.5.1 495 | The ``output`` keyword argument was added. 496 | 497 | .. index:: Key; importing 498 | 499 | .. index:: Key; receiving 500 | 501 | Importing and receiving keys 502 | ---------------------------- 503 | 504 | To import keys, get the key data as an ASCII string, say ``key_data``. Then you 505 | can call :meth:`~gnupg.GPG.import_keys` with it:: 506 | 507 | >>> import_result = gpg.import_keys(key_data) 508 | 509 | This will import all the keys in ``key_data``. The number of keys imported will be 510 | available in ``import_result.count`` and the fingerprints of the imported keys will be 511 | in ``import_result.fingerprints``. 512 | 513 | In addition, ``extra_args`` and ``passphrase`` keyword parameter can be specified. If 514 | provided, ``extra_args`` is treated as a list of additional arguments to pass to the 515 | ``gpg`` executable. If ``passphrase`` is specified, it is passed to ``gpgg`` for when 516 | an imported secret key has a passphrase. 517 | 518 | .. versionadded:: 0.4.5 519 | The ``extra_args`` keyword argument. 520 | 521 | .. versionadded:: 0.4.7 522 | The ``passphrase`` keyword argument. 523 | 524 | To import keys from a file, use :meth:`~gnupg.GPG.import_keys_file` instead:: 525 | 526 | >>> import_result = gpg.import_keys_file(key_path) 527 | 528 | This also takes the keyword arguments specified for :meth:`~gnupg.GPG.import_keys`. 529 | 530 | .. versionadded:: 0.5.0 531 | The :meth:`~gnupg.GPG.import_keys_file` method. 532 | 533 | To receive keys from a keyserver, use :meth:`~gnupg.GPG.recv_keys`:: 534 | 535 | >>> import_result = gpg.recv_keys('server-name', 'keyid1', 'keyid2', ...) 536 | 537 | This will fetch keys with all specified keyids and import them. Note that on Windows, 538 | you may require helper programs such as ``gpg_hkp.exe``, distributed with GnuPG, to 539 | successfully run ``recv_keys``. On Jython, security permissions may lead to failure of 540 | ``recv_keys``. 541 | 542 | Note that when you import keys, you may get spurious "key expired" / "signature 543 | expired" messages which are sent by ``gpg`` and collected by ``python-gnupg``. This 544 | may happen, for example, if there are subkey expiry dates which have been extended, so 545 | that the keys haven't actually expired, even when ``gpg`` sends messages that they 546 | have. Make sure you just look at the ``count`` and ``fingerprints`` attributes to 547 | identify the keys that were imported. 548 | 549 | .. index:: Key; listing 550 | 551 | Listing keys 552 | ------------ 553 | 554 | Now that we've seen how to generate, import and export keys, let's move on to 555 | finding which keys we have in our keyrings. This is fairly straightforward 556 | using the :meth:`~gnupg.GPG.list_keys` method:: 557 | 558 | >>> public_keys = gpg.list_keys() # same as gpg.list_keys(False) 559 | >>> private_keys = gpg.list_keys(True) # True => private keys 560 | 561 | The returned value from :meth:`~gnupg.GPG.list_keys` is a subclass of Python's 562 | ``list`` class. Each entry represents one key and is a Python dictionary which 563 | contains useful information about the corresponding key. 564 | 565 | The following entries are in the returned dictionary. Some of the key names are not 566 | ideal for describing the values, but they have been left as is for backward 567 | compatibility reasons. As `GnuPG documentation 568 | `_ has improved, a better 569 | understanding is possible of the information returned by ``gpg``. 570 | 571 | .. cssclass:: generic-table table-bordered table-responsive-sm table-striped mx-auto mb-3 colwidths-auto smaller hpad 572 | 573 | +-------------+--------------------------------------------------------------------------------+ 574 | | dict key | dict value (all string values) | 575 | +=============+================================================================================+ 576 | | type | Type of key | 577 | +-------------+--------------------------------------------------------------------------------+ 578 | | trust | The validity of the key | 579 | +-------------+--------------------------------------------------------------------------------+ 580 | | length | The length of the key in bits | 581 | +-------------+--------------------------------------------------------------------------------+ 582 | | algo | Public key algorithm | 583 | +-------------+--------------------------------------------------------------------------------+ 584 | | keyid | The key ID | 585 | +-------------+--------------------------------------------------------------------------------+ 586 | | date | The creation date of the key in UTC as a Unix timestamp | 587 | +-------------+--------------------------------------------------------------------------------+ 588 | | expires | The expiry date of the key in UTC as a timestamp, if specified | 589 | +-------------+--------------------------------------------------------------------------------+ 590 | | dummy | Certificate serial number, UID hash or trust signature info | 591 | +-------------+--------------------------------------------------------------------------------+ 592 | | ownertrust | The level of owner trust for the key | 593 | +-------------+--------------------------------------------------------------------------------+ 594 | | uid | The user ID | 595 | +-------------+--------------------------------------------------------------------------------+ 596 | | sig | Signature class | 597 | +-------------+--------------------------------------------------------------------------------+ 598 | | cap | Key capabilities | 599 | +-------------+--------------------------------------------------------------------------------+ 600 | | issuer | Issuer information | 601 | +-------------+--------------------------------------------------------------------------------+ 602 | | flag | A flag field | 603 | +-------------+--------------------------------------------------------------------------------+ 604 | | token | Token serial number | 605 | +-------------+--------------------------------------------------------------------------------+ 606 | | hash | Hash algorithm | 607 | +-------------+--------------------------------------------------------------------------------+ 608 | | curve | Curve name for elliptic curve cryptography (ECC) keys | 609 | +-------------+--------------------------------------------------------------------------------+ 610 | | compliance | Compliance flags | 611 | +-------------+--------------------------------------------------------------------------------+ 612 | | updated | Last updated timestamp | 613 | +-------------+--------------------------------------------------------------------------------+ 614 | | origin | Origin of keys | 615 | +-------------+--------------------------------------------------------------------------------+ 616 | | keygrip | Keygrip of keys (Note that you'll need GnuPG >= 2.1 for this to work.) | 617 | +-------------+--------------------------------------------------------------------------------+ 618 | | subkeys | A list containing [keyid, type, fingerprint, keygrip] elements for each subkey | 619 | +-------------+--------------------------------------------------------------------------------+ 620 | | subkey_info | A dictionary of subkey information keyed on subkey id | 621 | +-------------+--------------------------------------------------------------------------------+ 622 | 623 | Depending on the version of ``gpg`` used, some of these keys may have the value 624 | ``'unavailable'``. The last two keys are provided by ``python-gnupg`` rather than 625 | ``gpg``. 626 | 627 | For more information about the values in this dictionary, refer to the GnuPG 628 | documentation linked above. (Note that that documentation is not terribly 629 | user-friendly, but nevertheless it should be usable.) 630 | 631 | The returned value from :meth:`~gnupg.GPG.list_keys` has an attribute ``uids``, which is a 632 | list of userids associated with the listed keys, and an attribute ``fingerprints``, which 633 | is a list of the key fingerprints associated with the listed keys. 634 | 635 | .. versionadded:: 0.3.8 636 | The returned value from :meth:`~gnupg.GPG.list_keys` now has a new 637 | attribute, ``key_map``, which is a dictionary mapping key and subkey 638 | fingerprints to the corresponding key's dictionary. With this change, you 639 | don't need to iterate over the (potentially large) returned list to search 640 | for a key with a given fingerprint - the ``key_map`` dict will take you 641 | straight to the key info, whether the fingerprint you have is for a key or a 642 | subkey. 643 | 644 | .. versionadded:: 0.3.8 645 | You can also list a subset of keys by specifying a ``keys=`` keyword 646 | argument to :meth:`~gnupg.GPG.list_keys` whose value is either a single 647 | string matching a key, or a list of strings matching multiple keys. In this 648 | case, the return value only includes matching keys. 649 | 650 | .. versionadded:: 0.3.9 651 | A new ``sigs=`` keyword argument has been added to 652 | :meth:`~gnupg.GPG.list_keys`, defaulting to ``False``. If you specify true, 653 | the ``sigs`` entry in the key information returned will contain a list of 654 | signatures which apply to the key. Each entry in the list is a 3-tuple of 655 | (``keyid``, ``user-id``, ``signature-class``) where the ``signature-class`` 656 | is as defined by RFC-4880_. 657 | 658 | It doesn't make sense to supply both ``secret=True`` *and* ``sigs=True`` (people 659 | can't sign your secret keys), so in case ``secret=True`` is specified, the 660 | ``sigs=`` value has no effect. 661 | 662 | .. versionadded:: 0.4.1 663 | Instances of the ``GPG`` class now have an additional ``on_data`` attribute, which 664 | defaults to ``None``. It can be set to a callable which will be called with a 665 | single argument - a binary chunk of data received from the ``gpg`` executable. The 666 | callable can do whatever it likes with the chunks passed to it - e.g. write them to 667 | a separate stream. The callable should not raise any exceptions (unless it wants 668 | the current operation to fail). 669 | 670 | .. versionadded:: 0.4.2 671 | Information on keys returned by :meth:`~gnupg.GPG.list_keys` or 672 | :meth:`~gnupg.GPG.scan_keys` now incudes a ``subkey_info`` dictionary, which 673 | contains any returned information on subkeys such as creation and expiry 674 | dates. The dictionary is keyed on the subkey ID. The following additional 675 | keys are present in key information dictionaries: ``cap``, ``issuer``, 676 | ``flag``, ``token``, ``hash``, ``curve``, ``compliance``, ``updated`` and 677 | ``origin``. 678 | 679 | .. versionadded:: 0.4.4 680 | Instances of the ``GPG`` class now have an additional 681 | ``check_fingerprint_collisions`` attribute, which defaults to ``False``. If set to 682 | a truthy value, fingerprint collisions are checked for (and a ``ValueError`` raised 683 | if a collision is detected) when listing or scanning keys. It appears that ``gpg`` 684 | is quite lenient about allowing duplicated keys in keyrings, which would lead to 685 | collisions. 686 | 687 | .. versionchanged:: 0.4.4 688 | The ``on_data`` callable will now be called with an empty chunk when the data 689 | stream from ``gpg`` is exhausted. It can now also return a value: if the value 690 | ``False`` is returned, the chunk will *not* be buffered within ``python-gnupg``. 691 | This might be useful if you want to do your own buffering or avoid buffering 692 | altogether. If any other value is returned (including the value ``None``, for 693 | backward compatibility) the chunk will be buffered as normal by ``python-gnupg``. 694 | 695 | .. versionadded:: 0.4.6 696 | Instances of the ``GPG`` class now have an additional ``error_map`` attribute, 697 | which defaults to ``None``. If you set this, the value should be a dictionary 698 | mapping error codes to error messages. The source distribution includes a file 699 | ``messages.json`` which contains such a mapping, gleaned from the GnuPG library 700 | libgpg-error, version 1.37. The test suite shows how to convert that JSON to a form 701 | suitable for converting to an ``error_map`` value (basically, converting the string 702 | keys in the JSON to integers using base 16). 703 | 704 | .. versionadded:: 0.4.9 705 | Information on keys returned by :meth:`~gnupg.GPG.list_keys` now includes 706 | the ``keygrip`` attribute. The ``subkeys`` attribute now also consists of four 707 | values with the ``keygrip`` being the fourth. Note that you'll need GnuPG >= 708 | 2.1 for this to work. 709 | 710 | .. versionadded:: 0.5.4 711 | Instances of the result classes from operations now have an ``on_data_failure`` 712 | attribute, which defaults to ``None``. If an ``on_data`` callable raises an exception, 713 | the ``on_data_failure`` attribute of the returned object from a high-level operation 714 | is set to the first exception that was raised. The ``on_data`` callable will continue 715 | to be called with future chunks. If you use ``on_data`` with code that can raise any 716 | exceptions, be sure to check the ``on_data_failure`` attribute of a returned object 717 | before using any other aspects of the result. 718 | 719 | .. versionadded:: 0.5.5 720 | The returned value from :meth:`~gnupg.GPG.list_keys` now has a new 721 | attribute, ``uid_map``, which is a dictionary mapping uids to dicts with 722 | detailed information about the corresponding uid. The keys of the information 723 | provided are listed in the table above. Refer to the `GnuPG documentation 724 | `_ for more information. 725 | 726 | You could use this information as in the following example: 727 | 728 | .. code-block:: pycon 729 | 730 | >>> from pprint import pprint 731 | >>> keys = gpg.list_keys() 732 | >>> pprint(keys.uids) 733 | ['Andrew Able (A test user) ', 734 | 'Barb Bruin ', 735 | 'Babs Broon ', 736 | 'Barbara Brown (A test user) ', 737 | 'Charlie Clark (A test user) ', 738 | 'Donna Davis (A test user) '] 739 | >>> pprint(keys.uid_map('Barbara Brown (A test user) ') 740 | {'algo': '', 741 | 'date': '1739485458', 742 | 'dummy': '8B989767967370B894C53279A3BDF655F00CD4DE', 743 | 'expires': '', 744 | 'keyid': '', 745 | 'length': '', 746 | 'ownertrust': '', 747 | 'sig': '', 748 | 'trust': 'u', 749 | 'type': 'uid', 750 | 'uid': 'Barbara Brown (A test user) '} 751 | >>> pprint(keys.uid_map['Barb Bruin ']) 752 | {'algo': '', 753 | 'date': '1739485886', 754 | 'dummy': '951261047308BCA0B45FD738AD8630B336B88ECF', 755 | 'expires': '', 756 | 'keyid': '', 757 | 'length': '', 758 | 'ownertrust': '', 759 | 'sig': '', 760 | 'trust': 'u', 761 | 'type': 'uid', 762 | 'uid': 'Barb Bruin '} 763 | >>> pprint(keys.uid_map['Babs Broon ']) 764 | {'algo': '', 765 | 'date': '', 766 | 'dummy': '2BDB74660AC54DF33DE523429386E2D460904E74', 767 | 'expires': '', 768 | 'keyid': '', 769 | 'length': '', 770 | 'ownertrust': '', 771 | 'sig': '', 772 | 'trust': 'r', 773 | 'type': 'uid', 774 | 'uid': 'Babs Broon '} 775 | >>> 776 | 777 | The first two of these dictionaries show normal uids (trust is 'u', for ultimate), whereas the third 778 | shows a revoked uid (trust is 'r', for revoked). 779 | 780 | 781 | .. _RFC-4880: https://tools.ietf.org/html/rfc4880#section-5.2.1 782 | 783 | 784 | .. index:: Key; trusting 785 | 786 | Setting the trust level for imported keys 787 | ----------------------------------------- 788 | 789 | You can set the trust level for imported keys using 790 | :meth:`~gnupg.GPG.trust_keys`:: 791 | 792 | >>> gpg.trust_keys(fingerprints, trustlevel) 793 | 794 | where the ``fingerprints`` are a list of fingerprints of keys for which the trust 795 | level is to be set, and ``trustlevel`` is one of the string values ``'TRUST_EXPIRED'``, 796 | ``'TRUST_UNDEFINED'``, ``'TRUST_NEVER'``, ``'TRUST_MARGINAL'``, ``'TRUST_FULLY'`` or 797 | ``'TRUST_ULTIMATE'``. 798 | 799 | You can also specify a single fingerprint for the ``fingerprints`` parameter. 800 | 801 | .. versionadded:: 0.4.2 802 | The ``trust_keys`` method was added. 803 | 804 | .. index:: Key; scanning 805 | 806 | Scanning keys 807 | ------------- 808 | 809 | We can also scan keys in files without importing them into a local keyring, by 810 | using :meth:`~gnupg.GPG.scan_keys`:: 811 | 812 | >>> keys = gpg.scan_keys(key_file_name) 813 | 814 | The returned value from :meth:`~gnupg.GPG.scan_keys` has the same format as for 815 | :meth:`~gnupg.GPG.list_keys`. 816 | 817 | .. versionadded:: 0.3.7 818 | The :meth:`~gnupg.GPG.scan_keys` method was added. 819 | 820 | To scan keys in a string, we can use :meth:`~gnupg.GPG.scan_keys_mem` instead:: 821 | 822 | >>> keys = gpg.scan_keys_mem(key_text) 823 | 824 | The result will be the same as for :meth:`~gnupg.GPG.scan_keys`. 825 | 826 | .. versionadded:: 0.5.1 827 | The :meth:`~gnupg.GPG.scan_keys_mem` method was added. 828 | 829 | .. index:: Key; deleting 830 | 831 | Deleting keys 832 | ------------- 833 | 834 | To delete keys, their key identifiers must be specified. If a public/private keypair 835 | has been created, a private key needs to be deleted before the public key can be 836 | deleted, and for both you use the :meth:`~gnupg.GPG.delete_keys` method:: 837 | 838 | >>> key = gpg.gen_key(gpg.gen_key_input()) 839 | >>> fp = key.fingerprint 840 | >>> str(gpg.delete_keys(fp)) # same as gpg.delete_keys(fp, False) 841 | 'Must delete secret key first' 842 | >>> str(gpg.delete_keys(fp, True))# True => private keys 843 | 'ok' 844 | >>> str(gpg.delete_keys(fp)) 845 | 'ok' 846 | >>> str(gpg.delete_keys("nosuchkey")) 847 | 'No such key' 848 | 849 | The argument you pass to :meth:`~gnupg.GPG.delete_keys` can be either a single 850 | key identifier (e.g. keyid or fingerprint) or a sequence of key identifiers. 851 | 852 | The :meth:`~gnupg.GPG.delete_keys` method has some additional keyword arguments: 853 | 854 | * ``passphrase`` - if specified, sends the specified passphrase to ``gpg``. For GnuPG 855 | >= 2.1, exporting secret keys requires a passphrase to be provided. 856 | * ``expect_passphrase`` - defaults to ``True`` for backward compatibility. If the 857 | passphrase is to be passed to ``gpg`` via pinentry, you wouldn't pass it here - so 858 | specify ``expect_passphrase=False`` in that case. If you don't do that, and don't 859 | pass a passphrase, a ``ValueError`` will be raised. 860 | * ``exclamation_mode`` - defaults to ``False`` for backward compatibility. If the exclamation 861 | mode is set, and a fingerprint of a subkey is passed only that subkey will be deleted. If the 862 | fingerprint is of a primary key the entire key will be deleted. 863 | 864 | .. versionadded:: 0.4.0 865 | The ``passphrase`` keyword argument was added. 866 | 867 | .. versionadded:: 0.4.2 868 | The ``expect_passphrase`` keyword argument was added. 869 | 870 | .. versionadded:: 0.4.9 871 | The ``exclamation_mode`` keyword argument was added. 872 | 873 | 874 | .. index:: Key; searching 875 | 876 | Searching for keys 877 | ------------------ 878 | 879 | You can search for keys by passing a search query and optionally a keyserver 880 | name to the :meth:`~gnupg.GPG.search_keys`. If no keyserver is specified, 881 | ``pgp.mit.edu`` is used. A list of dictionaries describing keys that were found 882 | is returned (this list could be empty). For example:: 883 | 884 | >>> gpg.search_keys('vinay_sajip@hotmail.com', 'keyserver.ubuntu.com') 885 | [{'keyid': u'92905378', 'uids': [u'Vinay Sajip '], 'expires': u'', 'length': u'1024', 'algo': u'17', 'date': u'1221156445', 'type': u'pub'}] 886 | 887 | .. versionadded:: 0.3.5 888 | The :meth:`~gnupg.GPG.search_keys` method was added. 889 | 890 | .. index:: Key; sending 891 | 892 | Sending keys 893 | ------------ 894 | 895 | You can send keys to a keyserver by passing its name and some key identifiers 896 | to the :meth:`~gnupg.GPG.send_keys`. For example:: 897 | 898 | >>> gpg.send_keys('keyserver.ubuntu.com', '6E4D5A2B') 899 | 900 | 901 | .. versionadded:: 0.3.5 902 | The :meth:`~gnupg.GPG.send_keys` method was added. 903 | 904 | 905 | Encryption and Decryption 906 | ========================= 907 | 908 | Data intended for some particular recipients is encrypted with the public keys of 909 | those recipients. Each recipient can decrypt the encrypted data using the 910 | corresponding private key. 911 | 912 | .. index:: Encryption 913 | 914 | Encryption 915 | ---------- 916 | 917 | To encrypt a message, use the :meth:`~gnupg.GPG.encrypt` method:: 918 | 919 | >>> encrypted_ascii_data = gpg.encrypt(data, recipients) 920 | 921 | If you want to encrypt data in a file (or file-like object), use 922 | :meth:`~gnupg.GPG.encrypt_file` instead:: 923 | 924 | >>> encrypted_ascii_data = gpg.encrypt_file(stream, recipients) # e.g. after stream = open(filename, 'rb') 925 | 926 | These methods both return an object such that: 927 | 928 | * If encryption succeeded, the returned object's ``ok`` attribute is set to ``True`` 929 | and the ``data`` attribute holds the encrypted data. 930 | Otherwise, the returned object's ``ok`` attribute is set to ``False`` and its 931 | ``status`` attribute (a message string) provides more information as to the reason 932 | for failure (for example, ``'invalid recipient'`` or ``'key expired'``). 933 | * ``str(encrypted_ascii_data)`` gives the encrypted data in a non-binary format. 934 | 935 | In both cases, ``recipients`` is a list of key fingerprints for those recipients. For 936 | your convenience, if there is a single recipient, you can pass the fingerprint rather 937 | than a 1-element array containing the fingerprint. Both methods accept the following 938 | optional keyword arguments: 939 | 940 | sign (defaults to ``None``) 941 | Either the Boolean value ``True``, or the fingerprint of a key which is used to 942 | sign the encrypted data. If ``True`` is specified, the default key is used for 943 | signing. When not specified, the data is not signed. 944 | always_trust (defaults to ``False``) 945 | Skip key validation and assume that used keys are always fully trusted. 946 | passphrase (defaults to ``None``) 947 | A passphrase to use when accessing the keyrings. 948 | extra_args (defaults to ``None``) 949 | A list of additional arguments to pass to the ``gpg`` executable. For example, you 950 | could pass ``extra_args=['-z', '0']`` to disable compression, or you could pass 951 | ``extra_args=['--set-filename', 'name-to-embed-in-encrypted-file.txt']`` to embed 952 | a specific file name in the encrypted message. 953 | armor (defaults to ``True``) 954 | Whether to use ASCII armor. If ``False``, binary data is produced. 955 | output (defaults to ``None``) 956 | The name of an output file to write to. If a name is specified, the encrypted 957 | output is written directly to the file. 958 | 959 | .. index:: Encryption; symmetric 960 | 961 | symmetric (defaults to ``False``) 962 | If specified, symmetric encryption is used. In this case, specify recipients as 963 | ``None``. If ``True`` is specified, then the default cipher algorithm (``CAST5``) 964 | is used. Starting with version 0.3.5, you can also specify the cipher-algorithm to 965 | use (for example, ``'AES256'``). Check your ``gpg`` command line help to see what 966 | symmetric cipher algorithms are supported. Note that the default (``CAST5``) may 967 | not be the best available. 968 | 969 | .. versionchanged:: 0.3.5 970 | A string can be passed for the ``symmetric`` argument, as well as ``True`` or 971 | ``False``. If a string is passed, it should be a symmetric cipher algorithm 972 | supported by the ``gpg`` you are using. 973 | 974 | .. versionadded:: 0.4.1 975 | The ``extra_args`` keyword argument was added. 976 | 977 | .. versionadded:: 0.5.1 978 | The ``status_detail`` attribute was added to the result object. This attribute will 979 | be set when the result object's ``status`` attribute is set to ``invalid recipient`` 980 | and will contain more information about the failure in the form of ``reason:ident`` 981 | where ``reason`` is a text description of the reason, and ``ident`` identifies the 982 | recipient key. 983 | 984 | .. note:: Any public key provided for encryption should be trusted, otherwise 985 | encryption fails but without any warning. This is because gpg just prints a message 986 | to the console, but does not provide a specific error indication that the Python 987 | wrapper can use. 988 | 989 | .. versionchanged:: 0.5.0 990 | The `stream` argument to :meth:`~gnupg.GPG.encrypt_file` can be a pathname 991 | to an existing file as well as text or a file-like object. In the pathname 992 | case, ``python-gnupg`` will open and close the file for you. 993 | 994 | .. note:: 995 | ``python-gnupg`` assumes that any object with a :attr:`read` attribute is a 996 | file-like object. Otherwise, if it corresponds to an existing file, then it is taken 997 | as a filename, and otherwise it must be the actual data to be processed. 998 | 999 | 1000 | .. index:: Decryption 1001 | 1002 | Decryption 1003 | ---------- 1004 | 1005 | To decrypt a message, use the :meth:`~gnupg.GPG.decrypt` method:: 1006 | 1007 | >>> decrypted_data = gpg.decrypt(data) 1008 | 1009 | If you want to decrypt data in a file (or file-like object), use 1010 | :meth:`~gnupg.GPG.decrypt_file` instead:: 1011 | 1012 | >>> decrypted_data = gpg.decrypt_file(stream) # e.g. after stream = open(filename, 'rb') 1013 | 1014 | These methods both return an object such that ``str(decrypted_data)`` gives the 1015 | decrypted data in a non-binary format. If decryption succeeded, the returned object's 1016 | ``ok`` attribute is set to ``True`` and the ``data`` attribute holds the decrypted 1017 | data. Otherwise, the returned object's ``ok`` attribute is set to ``False`` and its 1018 | ``status`` attribute (a message string) provides more information as to the reason for 1019 | failure (for example, ``'bad passphrase'`` or ``'decryption failed'``). 1020 | 1021 | Both methods accept the following optional keyword arguments: 1022 | 1023 | always_trust (defaults to ``False``) 1024 | Skip key validation and assume that used keys are always fully trusted. 1025 | passphrase (defaults to ``None``) 1026 | A passphrase to use when accessing the keyrings. 1027 | extra_args (defaults to ``None``) 1028 | A list of additional arguments to pass to the ``gpg`` executable. 1029 | output (defaults to ``None``) 1030 | The name of an output file to write to. If a name is specified, the decrypted 1031 | output is written directly to the file. 1032 | 1033 | .. versionadded:: 0.4.1 1034 | The ``extra_args`` keyword argument was added. 1035 | 1036 | .. versionadded:: 0.4.2 1037 | Upon a successful decryption, the keyid of the decrypting key is stored in the 1038 | ``key_id`` attribute of the result, if this information is provided by ``gpg``. 1039 | 1040 | .. versionchanged:: 0.5.0 1041 | The `stream` argument to :meth:`~gnupg.GPG.decrypt_file` can be a pathname 1042 | to an existing file as well as text or a file-like object. In the pathname 1043 | case, ``python-gnupg`` will open and close the file for you. 1044 | 1045 | .. _caching-warning: 1046 | 1047 | .. warning:: 1048 | **Passphrase caching:** By default, ``gpg-agent`` caches passphrases, and this can 1049 | lead to unexpected results such as successfully decrypting messages even when 1050 | passing the wrong passphrase. To avoid this, disable caching by putting the 1051 | following two lines in ``gpg-agent.conf``: 1052 | 1053 | * ``default-cache-ttl 0`` and either 1054 | * ``maximum-cache-ttl 0`` for GnuPG < 2.1, or 1055 | * ``max-cache-ttl 0`` for GnuPG >= 2.1. 1056 | 1057 | For more information, see the `GnuPG documentation on agent configuration 1058 | `_. 1059 | 1060 | Using signing and encryption together 1061 | ------------------------------------- 1062 | 1063 | If you want to use signing and encryption together, use the 1064 | :meth:`~gnupg.GPG.encrypt` with a signer fingerprint and the corresponding 1065 | passphrase:: 1066 | 1067 | >>> encrypted_data = gpg.encrypt(data, recipients, sign=signer_fingerprint, passphrase=signer_passphrase) 1068 | 1069 | The resulting encrypted data contains the signature. When decrypting the data, upon 1070 | successful decryption, signature verification is also performed (assuming the relevant 1071 | public keys are available at the recipient end). The results are stored in the object 1072 | returned from the :meth:`~gnupg.GPG.decrypt` call:: 1073 | 1074 | >>> decrypted_data = gpg.decrypt(data, passphrase=recipient_passphrase) 1075 | 1076 | At this point, if a signature is verified, signer information is held in attributes of 1077 | ``decrypted_data``: ``username``, ``key_id``, ``signature_id``, ``fingerprint``, 1078 | ``trust_level`` and ``trust_text``. If the message wasn't signed, these attributes 1079 | will all be set to ``None``. 1080 | 1081 | The trust levels are (in increasing order) ``TRUST_UNDEFINED``, ``TRUST_NEVER``, 1082 | ``TRUST_MARGINAL``, ``TRUST_FULLY`` and ``TRUST_ULTIMATE``. If verification succeeded, 1083 | you can test the trust level against known values as in the following example:: 1084 | 1085 | decrypted_data = gpg.decrypt(data, passphrase=recipient_passphrase)) 1086 | if decrypted_data.trust_level is not None and decrypted_data.trust_level >= decrypted_data.TRUST_FULLY: 1087 | print('Trust level: %s' % decrypted_data.trust_text) 1088 | 1089 | .. versionadded:: 0.3.1 1090 | The ``trust_level`` and ``trust_text`` attributes were added. 1091 | 1092 | 1093 | Finding the recipients for an encrypted message 1094 | ----------------------------------------------- 1095 | 1096 | Sometimes, it's desirable to find the recipients for an encrypted message, 1097 | without actually performing decryption. You can do this using the 1098 | :meth:`~gnupg.GPG.get_recipients` or 1099 | :meth:`~gnupg.GPG.get_recipients_file` methods: 1100 | 1101 | >>> ids = gpg.get_recipients(data) 1102 | 1103 | or, with a file or file-like object: 1104 | 1105 | >>> ids = gpg.get_recipients_file(stream) # e.g. after stream = open(filename, 'rb') 1106 | 1107 | .. versionadded:: 0.4.8 1108 | The ``get_recipients`` and ``get_recipients_file`` methods were added. 1109 | 1110 | .. versionchanged:: 0.5.0 1111 | The `stream` argument to :meth:`~gnupg.GPG.get_recipients_file` can be a 1112 | pathname to an existing file as well as text or a file-like object. In the 1113 | pathname case, ``python-gnupg`` will open and close the file for you. 1114 | 1115 | 1116 | Custom handling of data streams 1117 | ------------------------------- 1118 | 1119 | During processing, ``gpg`` often sends output to its ``stdout`` stream, which is captured 1120 | by ``python-gnupg`` buffered, and returned as part of an operation's result (usually in 1121 | the ``data`` attribute). However, there might be times when you want to: 1122 | 1123 | * Avoid buffering, as the data sizes involved are large. 1124 | * Process the data as it becomes available, before it's all available at the end of an 1125 | operation. Most commonly, this will happen during decryption. 1126 | 1127 | In such cases, you can supply a callable in the ``on_data`` attribute of a :class:`GPG` 1128 | instance before you invoke the operation. When an operation with ``gpg`` is initiated, if 1129 | ``on_data`` is given a value, it will be called with each chunk of data (of type 1130 | ``bytes``) received from ``gpg``, and its return value will be used to determine whether 1131 | ``python-gnupg`` buffers the data. At the end of the data stream, it will be called with 1132 | a zero-length bytestring (allowing you do any necessary clean-up). 1133 | 1134 | If the ``on_data`` callable returns ``False``, the data will *not* be buffered by 1135 | ``python-gnupg``. For any other return value (including ``None``), the data *will* be 1136 | buffered. (This slightly odd arrangement is for backwards compatibility.) 1137 | 1138 | Example usages (not tested, error handling omitted): 1139 | 1140 | .. code-block:: python 1141 | 1142 | # Doing your own buffering in memory 1143 | 1144 | chunks = [] 1145 | 1146 | def collector(chunk): 1147 | chunks.append(chunk) 1148 | return False # Tell python-gnupg not to buffer the chunk 1149 | 1150 | gpg = GPG(...) 1151 | gpg.on_data = collector 1152 | gpg.decrypt(...) 1153 | 1154 | # Doing your own buffering in a file 1155 | 1156 | class Collector: 1157 | def __init__(self, fn): 1158 | self.out = open(fn, 'wb') 1159 | 1160 | def __call__(self, chunk): 1161 | self.out.write(chunk) 1162 | if not chunk: 1163 | self.out.close() 1164 | return False # Tell python-gnupg not to buffer the chunk 1165 | 1166 | gpg = GPG(...) 1167 | gpg.on_data = Collector('/tmp/plain.txt') 1168 | gpg.decrypt(...) 1169 | 1170 | # Processing as you go (assuming the decrypted data is utf-8 encoded) 1171 | 1172 | import codecs 1173 | 1174 | class Processor: 1175 | def __init__(self, fn): 1176 | self.out = open(fn, 'w', encoding='utf-8') 1177 | self.decoder = codecs.getincrementaldecoder('utf-8') 1178 | self.result = '' 1179 | 1180 | def __call__(self, chunk): 1181 | final = (len(chunk) == 0) 1182 | self.result += self.decoder.decode(chunk, final) 1183 | # Perhaps do custom processing of self.result here 1184 | self.out.write(self.result) 1185 | self.result = '' 1186 | if final: 1187 | self.out.close() 1188 | return False # Tell python-gnupg not to buffer the chunk 1189 | 1190 | gpg = GPG(...) 1191 | gpg.on_data = Processor('/tmp/plain.txt') 1192 | gpg.decrypt(...) 1193 | 1194 | 1195 | Threading constraints on processing data 1196 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 1197 | 1198 | The `on_data` callable is called from a background thread which is reading data from the 1199 | `gpg` child process. Sometimes, there are constraints on where certain processing can be 1200 | done (e.g. code involving SQLAlchemy sessions or Qt GUI updates needs to be run on a 1201 | specific thread, not just any thread). To handle this, you can use a queue, as in this 1202 | example (not tested, error handling omitted): 1203 | 1204 | .. code-block:: python 1205 | 1206 | import queue 1207 | 1208 | class ChunkForwarder: 1209 | def __init__(self, queue): 1210 | self.queue = queue 1211 | 1212 | def __call__(self, chunk): 1213 | self.queue.put(chunk) 1214 | return False # Tell python-gnupg not to buffer the chunk 1215 | 1216 | # In the thread where you need to process chunks 1217 | gpg = GPG(...) 1218 | q = queue.Queue() 1219 | gpg.on_data = ChunkForwarder(q) 1220 | # call the operation you want to perform. Chunks will be sent to the queue. 1221 | gpg.decrypt(...) 1222 | while True: 1223 | chunk = q.get() 1224 | q.task_done() # keep things tidy 1225 | if not chunk: 1226 | break 1227 | # process the chunk using a SQLAlchemy session, Qt widget or whatever 1228 | process_chunk(chunk) 1229 | 1230 | 1231 | Signing and Verification 1232 | ======================== 1233 | 1234 | Data intended for digital signing is signed with the private key of the signer. Each 1235 | recipient can verify the signed data using the corresponding public key. 1236 | 1237 | .. index:: Signing 1238 | 1239 | Signing 1240 | ------- 1241 | 1242 | To sign a message, use the :meth:`~gnupg.GPG.sign` method:: 1243 | 1244 | >>> signed_data = gpg.sign(message) 1245 | 1246 | or, for data in a file (or file-like object), you can use the 1247 | :meth:`~gnupg.GPG.sign_file` method instead:: 1248 | 1249 | >>> signed_data = gpg.sign_file(stream) # e.g. after stream = open(filename, "rb") 1250 | 1251 | These methods both return an object such that ``str(signed_data)`` gives the signed 1252 | data in a non-binary format. They accept the following optional keyword arguments: 1253 | 1254 | keyid (defaults to ``None``) 1255 | The id for the key which will be used to do the signing. If not specified, the 1256 | first key in the secret keyring is used. 1257 | passphrase (defaults to ``None``) 1258 | A passphrase to use when accessing the keyrings. 1259 | clearsign (defaults to ``True``) 1260 | Returns a clear text signature, i.e. one which can be read without any special 1261 | software. 1262 | detach (defaults to ``False``) 1263 | Returns a detached signature. If you specify ``True`` for this, then the detached 1264 | signature will not be clear text, i.e. it will be as if you had specified a 1265 | ``False`` value for *clearsign*. This is because if both are specified, gpg 1266 | ignores the request for a detached signature. 1267 | binary (defaults to ``False``) 1268 | If ``True``, a binary signature (rather than armored ASCII) is created. 1269 | output (defaults to ``None``) 1270 | If specified, this is used as the file path where GPG outputs the signature. 1271 | Convention dictates a ``.asc`` or ``.sig`` file extension for this. 1272 | extra_args (defaults to ``None``) 1273 | A list of additional arguments to pass to the ``gpg`` executable. 1274 | 1275 | Note: If the data being signed is binary, calling ``str(signed_data)`` may raise 1276 | exceptions. In that case, use the fact that ``signed_data.data`` holds the binary 1277 | signed data. Usually the signature itself is ASCII; it's the message itself which may 1278 | cause the exceptions to be raised. (Unless a detached signature is requested, the 1279 | result of signing is the message with the signature appended.) 1280 | 1281 | The hash algorithm used when creating the signature can be found in the 1282 | ``signed_data.hash_algo`` attribute. 1283 | 1284 | .. versionadded:: 0.2.5 1285 | The ``detach`` keyword argument was added in version 0.2.5. 1286 | 1287 | .. versionadded:: 0.2.6 1288 | The ``binary`` keyword argument was added in version 0.2.6. 1289 | 1290 | .. versionadded:: 0.3.7 1291 | The ``output`` keyword argument was added in version 0.3.7. 1292 | 1293 | .. versionadded:: 0.4.1 1294 | The ``extra_args`` keyword argument was added. 1295 | 1296 | .. versionadded:: 0.4.2 1297 | The keyid and username of the signing key are stored in the ``key_id`` and 1298 | ``username`` attributes of the result, if this information is provided by ``gpg`` 1299 | (which should happen if you specify ``extra_args=['--verbose']``). 1300 | 1301 | .. versionchanged:: 0.5.0 1302 | The *stream* argument to :meth:`~gnupg.GPG.sign_file` can be a pathname to 1303 | an existing file as well as text or a file-like object. In the pathname 1304 | case, ``python-gnupg`` will open and close the file for you. 1305 | 1306 | .. versionadded:: 0.5.1 1307 | The ``status_detail`` attribute was added to the result object. This attribute will 1308 | be set when the result object's ``status`` attribute is set to ``invalid signer`` 1309 | and will contain more information about the failure in the form of ``reason:ident`` 1310 | where ``reason`` is a text description of the reason, and ``ident`` identifies the 1311 | signing key. 1312 | 1313 | .. index:: Verification 1314 | 1315 | Verification 1316 | ------------ 1317 | 1318 | To verify some data which you've received, use the 1319 | :meth:`~gnupg.GPG.verify` method:: 1320 | 1321 | >>> verified = gpg.verify(data) 1322 | 1323 | To verify data in a file (or file-like object), use :meth:`~gnupg.GPG.verify_file`:: 1324 | 1325 | >>> verified = gpg.verify_file(stream) # e.g. after stream = open(filename, "rb") 1326 | 1327 | You can use the returned value in a Boolean context:: 1328 | 1329 | >>> if not verified: raise ValueError("Signature could not be verified!") 1330 | 1331 | Getting the signed data out while verifying 1332 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 1333 | 1334 | If you clearsign data, the signature envelops the signed data (whether text or 1335 | binary) with the signature, but by default you won't get this data back from a 1336 | :meth:`~gnupg.GPG.verify` or :meth:`~gnupg.GPG.verify_file` call. In order to 1337 | extract the signed data, you need to pass more information to the ``verify`` 1338 | methods about where you want that data (if none is specified, the data is 1339 | discarded). To write it to ``gpg``'s standard output, specify 1340 | ``extra_args=['-o', '-']``. In that case, it will be returned as a bytestring 1341 | in ``verified.data``. Alternatively, to write to a file, you can pass 1342 | ``extra_args=['-o', 'path/to/write/data.to']`` and it will be written to the 1343 | file you specify. (Thanks to Mark Neil for this suggestion.) 1344 | 1345 | 1346 | Verifying detached signatures on disk 1347 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 1348 | 1349 | If you want to verify a detached signature, use :meth:`~gnupg.GPG.verify_file`:: 1350 | 1351 | >>> verified = gpg.verify_file(stream, path_to_data_file) 1352 | 1353 | Note that in this case, the ``stream`` contains the *signature* to be verified. The 1354 | data that was signed should be in a separate file whose path is indicated by 1355 | ``path_to_data_file``. 1356 | 1357 | .. versionadded:: 0.2.5 1358 | The second argument to verify_file (``data_filename``) was added. 1359 | 1360 | .. versionadded:: 0.4.1 1361 | An optional keyword argument to verify_file (``close_file``) was added. This 1362 | defaults to ``True``, but if set to ``False``, the signature stream is not closed. 1363 | It's then left to the caller to close it when appropriate. 1364 | 1365 | An optional keyword argument ``extra_args`` was added. This defaults to ``None``, 1366 | but if a value is specified, it should be a list of extra arguments to pass to the 1367 | ``gpg`` executable. 1368 | 1369 | .. versionadded:: 0.4.4 1370 | When signature verification is performed, multiple signatures might be present. 1371 | Information about all signatures is now captured in a ``sig_info`` attribute of the 1372 | value returned from ``verify``. This is a dictionary keyed by the signature ID and 1373 | whose values are dictionaries containing the following information (note - all are 1374 | string values): 1375 | 1376 | * ``fingerprint`` - the fingerprint of the signing key. * ``pubkey_fingerprint`` - 1377 | this is usually the same as ``fingerprint``, but it might be different if a 1378 | subkey was used for the signing. 1379 | 1380 | * ``keyid`` - the key id. 1381 | 1382 | * ``username`` - user information for the signing key. 1383 | 1384 | * ``status`` - this indicates the status of the signature. 1385 | 1386 | * ``creation_date`` - the creation date of the signature in text format, YYYY-MM-DD. 1387 | 1388 | * ``timestamp`` - the signature creation time as a timestamp. 1389 | 1390 | * ``expiry`` - the signature expiry time as a timestamp, or ``'0'`` to 1391 | indicate no expiry. 1392 | 1393 | * ``trust_level`` - the trust level, see below. 1394 | 1395 | * ``trust_text`` - the text corresponding to the trust level. 1396 | 1397 | Note that only information for valid signatures will be present in ``sig_info``. 1398 | 1399 | When a signature is verified, signer information is held in attributes of 1400 | ``verified``: ``username``, ``key_id``, ``signature_id``, ``fingerprint``, 1401 | ``trust_level`` and ``trust_text``. If the message wasn't signed, these attributes 1402 | will all be set to ``None``. If there were multiple signatures, the last values seen 1403 | will be shown. 1404 | 1405 | The trust levels are (in increasing order) TRUST_UNDEFINED, TRUST_NEVER, 1406 | TRUST_MARGINAL, TRUST_FULLY and TRUST_ULTIMATE. If verification succeeded, you can 1407 | test the trust level against known values as in the following example:: 1408 | 1409 | verified = gpg.verify(data) 1410 | if verified.trust_level is not None and verified.trust_level >= verified.TRUST_FULLY: 1411 | print('Trust level: %s' % verified.trust_text) 1412 | 1413 | .. versionadded:: 0.3.1 1414 | The ``trust_level`` and ``trust_text`` attributes were added. 1415 | 1416 | Note that even if you have a valid signature, you may want to not rely on that 1417 | validity, if the key used for signing has expired or was revoked. If this information 1418 | is available, it will be in the ``key_status`` attribute =, and the result will still 1419 | be ``False`` in a Boolean context. If there is no problem detected with the signing 1420 | key, the ``key_status`` attribute will be ``None``. 1421 | 1422 | .. versionadded:: 0.3.3 1423 | The ``key_status`` attribute was added. 1424 | 1425 | .. versionadded:: 0.4.2 1426 | The keyid and username of the signing key are stored in the ``key_id`` and 1427 | ``username`` attributes of the result, if this information is provided by ``gpg``. 1428 | 1429 | .. versionchanged:: 0.5.0 1430 | The `stream` argument to :meth:`~gnupg.GPG.verify_file` can be a pathname to 1431 | an existing file as well as text or a file-like object. In the pathname 1432 | case, ``python-gnupg`` will open and close the file for you. 1433 | 1434 | .. versionadded:: 0.5.1 1435 | A ``problems`` attribute was added which holds problems reported by ``gpg`` 1436 | during verification. This is a list of dictionaries, one for each reported 1437 | problem. Each dictionary will have ``status`` and ``keyid`` keys indicating 1438 | the problem and the corresponding key; other information in the dictionaries 1439 | will be error specific. 1440 | 1441 | 1442 | Verifying detached signatures in memory 1443 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 1444 | 1445 | You can also verify detached signatures where the data is in memory, using 1446 | :meth:`~gnupg.GPG.verify_data`:: 1447 | 1448 | >>> verified = gpg.verify_data(path_to_signature_file, data) 1449 | 1450 | where *data* should be a byte string of the data to be verified against the signature 1451 | in the file named by *path_to_signature_file*. The returned value is the same as for 1452 | the other verification methods. 1453 | 1454 | In addition, an ``extra_args`` keyword parameter can be specified. If provided, this 1455 | is treated as a list of additional arguments to pass to the ``gpg`` executable. 1456 | 1457 | .. versionadded:: 0.3.6 1458 | The :meth:`~gnupg.GPG.verify_data` method was added. 1459 | 1460 | .. versionadded:: 0.4.1 1461 | The ``extra_args`` keyword argument was added. 1462 | 1463 | Accessing gpg's Return Code 1464 | =========================== 1465 | 1466 | Starting with version 0.4.8, return values to all calls which implement ``gpg`` 1467 | operations, other than :meth:`~gnupg.GPG.export_keys`, will have a ``returncode`` 1468 | attribute which is the return code returned by the ``gpg`` invocation made to perform the 1469 | operation (the result of :meth:`~gnupg.GPG.export_keys` is the set of exported keys and 1470 | doesn't have this attribute). 1471 | 1472 | .. versionadded:: 0.4.8 1473 | The ``returncode`` attribute was added to result instances. 1474 | 1475 | Passphrases 1476 | =========== 1477 | 1478 | Passphrases provided to ``python-gnupg`` are not stored persistently, and just passed 1479 | through to the ``GnuPG`` executable through a pipe. The user of ``python-gnupg`` is 1480 | responsible for taking care not to store passphrases where they may become available 1481 | to malicious code or malicious users, as well as the physical and security aspects of 1482 | managing their private keys. 1483 | 1484 | 1485 | .. index:: Logging 1486 | 1487 | .. _logging: 1488 | 1489 | Logging 1490 | ======= 1491 | 1492 | The module makes use of the facilities provided by Python's ``logging`` package. A 1493 | single logger is created with the module's ``__name__``, hence ``gnupg`` unless you 1494 | rename the module. A ``NullHandler`` instance is added to this logger, so if you don't 1495 | use logging in your application which uses this module, you shouldn't see any logging 1496 | messages. If you do use logging in your application, just configure it in the normal 1497 | way. 1498 | 1499 | .. index:: Download 1500 | 1501 | Test Harness 1502 | ============ 1503 | 1504 | The distribution includes a test harness, ``test_gnupg.py``, which contains unit tests 1505 | covering the functionality described above. You can invoke ``test_gnupg.py`` with one 1506 | or more optional command-line arguments. If no arguments are provided, all tests are 1507 | run. If arguments are provided, they collectively determine which of the tests will be 1508 | run: 1509 | 1510 | import 1511 | Run tests relating to key import 1512 | crypt 1513 | Run tests relating to encryption and decryption 1514 | sign 1515 | Run tests relating to signing and verification 1516 | key 1517 | Run tests relating to key management 1518 | basic 1519 | Run basic tests relating to environment setup, or which don't fit into one of the 1520 | above categories 1521 | 1522 | Download 1523 | ======== 1524 | 1525 | The latest version is available from the `PyPI 1526 | `_ page. 1527 | 1528 | The source code repository can be found `here 1529 | `__. 1530 | 1531 | Status and Further Work 1532 | ======================= 1533 | 1534 | The ``gnupg`` module, being based on proven earlier versions, is quite usable, and 1535 | comes packaged with Linux distributions such as Debian, Ubuntu and Fedora. However, 1536 | there may be some features of GnuPG which this module does not take advantage of, or 1537 | provide access to. How this module evolves will be determined by feedback from its 1538 | user community. 1539 | 1540 | Support for GnuPG 2.1 is limited, because that version of GnuPG does not provide the 1541 | ability to prevent pinentry popups in all cases. This package sends passphrases to the 1542 | ``gpg`` executable via pipes, which is only possible under GnuPG 2.1 under limited 1543 | conditions and requiring end-users to edit GnuPG configuration files. 1544 | 1545 | At present, functionality that requires interacting with the ``gpg`` executable (e.g. 1546 | for key editing) is not available. This is because it requires essentially a state 1547 | machine which manages the interaction - moreover, a state machine which varies 1548 | according to the specific version of the ``gpg`` executable being used. 1549 | 1550 | If you find bugs and want to raise issues, please do so via the `project issue tracker 1551 | `_. 1552 | 1553 | All feedback will be gratefully received; please send it to the `discussion group 1554 | `_. 1555 | 1556 | .. cssclass:: hidden 1557 | 1558 | Index 1559 | ===== 1560 | 1561 | * :ref:`genindex` 1562 | --------------------------------------------------------------------------------