diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..26e3729 --- /dev/null +++ b/.gitattributes @@ -0,0 +1 @@ +src/_version.py export-subst diff --git a/.gitignore b/.gitignore index c2b65d1..1b0ee02 100644 --- a/.gitignore +++ b/.gitignore @@ -35,11 +35,13 @@ nosetests.xml .pydevproject # Temp files +.\#* \#*\# *~ # tags TAGS +tags # notes *.org @@ -47,3 +49,26 @@ TAGS # Ignore log files and directories from tests: keys/* *.log + +# Ignore distutils record of installed files: +installed-files.txt + +# Ignore PyCharm files: +.idea/* + +# and git-tickets and tickets: +.tickets/* +tickets/* + +# Ignore virtualenv folders, if they are here: +include/* +local/* + +# Ignore gpg binary symlinks: +gpg + +# Ignore keys generated during tests: +*generated-keys* +*.pubring +*.secring +*random_seed* diff --git a/COPYLEFT b/COPYLEFT deleted file mode 100644 index 6a810bf..0000000 --- a/COPYLEFT +++ /dev/null @@ -1,12 +0,0 @@ - This file is part of python-gnupg, a Python wrapper around GnuPG. - Copyright (C) 2013 Isis Lovecruft - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as published - by the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. diff --git a/Makefile b/Makefile index c765da6..4571e0f 100644 --- a/Makefile +++ b/Makefile @@ -1,18 +1,65 @@ -clean: - rm -f \#*\# - rm -f ./*.pyc - rm -f ./*.pyo +ctags: + ctags -R *.py -cleantest: clean - mkdir -p keys +etags: + find . -name "*.py" -print | xargs etags + +cleanup-src: + cd src && \ + rm -f \#*\# && \ + rm -f ./*.pyc && \ + rm -f ./*.pyo + +cleanup-tests: + cd tests && \ + rm -f \#*\# && \ + rm -f ./*.pyc && \ + rm -f ./*.pyo + mkdir -p tests/tmp + mkdir -p tests/logs + touch tests/placeholder.log + mv tests/*.log tests/logs/ + rm tests/logs/placeholder.log touch placeholder.log - rm -rf keys rm *.log + rm tests/random_seed -test: cleantest - python test_gnupg.py basic +cleanup-tests-all: cleanup-tests + rm -rf tests/tmp + +cleanup-build: + mkdir buildnot + rm -rf build* + +test: cleanup-src cleanup-tests + which gpg + gpg --version + which gpg2 + gpg2 --version + which gpg-agent + which pinentry + which python + python --version + which pip + pip --version + pip list + python tests/test_gnupg.py parsers basic encodings genkey sign listkeys crypt keyrings import install: - python setup.py install + python setup.py install --record installed-files.txt +uninstall: + touch installed-files.txt + cat installed-files.txt | sudo xargs rm -rf + +cleandocs: + sphinx-apidoc -F -A "Isis Agora Lovecruft" -H "python-gnupg" -V 0.4.0 -R 0.4.0 -o docs src/ tests/ + +docs: + cd docs + make clean + make html + +venv: + -source /usr/shared/python/ns/virtualenvwrapper.sh && mkvirtualenv -a "$PWD" --no-site-packages --unzip-setuptools --distribute python-gnupg diff --git a/PKG-INFO b/PKG-INFO index 7acb3ca..206db4c 100644 --- a/PKG-INFO +++ b/PKG-INFO @@ -5,24 +5,25 @@ Summary: A wrapper for the Gnu Privacy Guard (GPG or GnuPG) Home-page: https://www.github.com/isislovecruft/python-gnupg Author: Isis Lovecruft Author-email: isis@leap.se -License: Copyright (C) 2013 by Isis Lovecruft. All Rights Reserved. See LICENSE for license. See COPYLEFT for "copyright". -Download-URL: https://github.com/isislovecruft/python-gnupg.git -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. -Platform: No particular restrictions -Classifier: Development Status :: 3 - Alpha -Classifier: Intended Audience :: Developers -Classifier: License :: OSI Approved :: GNU Affero General Public License v3 or later (AGPLv3+) -Classifier: Programming Language :: Python -Classifier: Programming Language :: Python :: 2 -Classifier: Programming Language :: Python :: 3 -Classifier: Programming Language :: Python :: 2.4 -Classifier: Programming Language :: Python :: 2.5 -Classifier: Programming Language :: Python :: 2.6 -Classifier: Programming Language :: Python :: 2.7 -Classifier: Programming Language :: Python :: 3.0 -Classifier: Programming Language :: Python :: 3.1 -Classifier: Programming Language :: Python :: 3.2 -Classifier: Operating System :: OS Independent -Classifier: Topic :: Security :: Cryptography -Classifier: Topic :: Software Development :: Libraries :: Python Modules -Classifier: Topic :: Utilities +Download-URL: https://github.com/isislovecruft/python-gnupg/archives/develop.zip +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.6 or greater. +Classifier:: Development Status :: 3 - Alpha +License :: OSI Approved :: GNU Affero General Public License v3 or later (AGPLv3+) +Operating System :: MacOS :: MacOS X +Operating System :: Microsoft :: Windows :: Windows 7 +Operating System :: Microsoft :: Windows :: Windows XP +Operating System :: POSIX :: BSD +Operating System :: POSIX :: Linux +Classifier:: Intended Audience :: Developers +Classifier:: License :: OSI Approved :: GNU Affero General Public License v3 or later (AGPLv3+) +Classifier:: Programming Language :: Python +Classifier:: Programming Language :: Python :: 2 +Classifier:: Programming Language :: Python :: 3 +Classifier:: Programming Language :: Python :: 2.6 +Classifier:: Programming Language :: Python :: 2.7 +Classifier:: Programming Language :: Python :: 3.0 +Classifier:: Programming Language :: Python :: 3.1 +Classifier:: Programming Language :: Python :: 3.2 +Classifier:: Topic :: Security :: Cryptography +Classifier:: Topic :: Software Development :: Libraries :: Python Modules +Classifier:: Topic :: Utilities diff --git a/README b/README deleted file mode 100644 index b553aa2..0000000 --- a/README +++ /dev/null @@ -1,12 +0,0 @@ -python-gnupg -============ - -Fork of python-gnupg-0.3.2, patched to remove Popen([...], shell=True). - -Installation ------------- -To install this package from a source distribution, do the following. - -1. Extract all the files in the distribution archive to some directory on your system. -2. In that directory, run "python setup.py install". -3. Optionally, run "python test_gnupg.py" to ensure that the package is working as expected. diff --git a/README.md b/README.md new file mode 100644 index 0000000..1d70df3 --- /dev/null +++ b/README.md @@ -0,0 +1,63 @@ +# python-gnupg # +================ + +Fork of python-gnupg-0.3.2, patched to remove ```Popen([...], shell=True)```. + +### Installation ### + +#### From this git repository #### +To install this package from this git repository, do: + +``` +git clone https://github.com/isislovecruft/python-gnupg.git +cd python-gnupg +make install +make test +``` + +Optionally to build the documentation after installation, do: +``` +make docs +``` + +To get started using python-gnupg's API, see the [online documentation](https://python-gnupg.readthedocs.org/en/latest/), +and import the module like so: +``` +>>> import gnupg +``` + +The primary interface class you'll likely want to interact with is +[```gnupg.GPG```](https://python-gnupg.readthedocs.org/en/latest/gnupg.html#gpg): +``` +>>> gpg = gnupg.GPG(gpgbinary='/usr/bin/gpg', +... gpghome='./keys', +... pubring='pubring.gpg', +... secring='secring.gpg') +>>> batch_key_input = gpg.gen_key_input() +>>> print batch_key_input +Key-Type: RSA +Name-Email: isis@wintermute +Name-Comment: Generated by gnupg.py +Key-Length: 4096 +Name-Real: Autogenerated Key +%pubring /home/isis/code/python-gnupg/keys/pubring.gpg +%secring /home/isis/code/python-gnupg/keys/secring.gpg +%commit + +>>> key = gpg.gen_key(batch_key_input) +>>> print key.fingerprint +245D8FA30F543B742053949F553C0E154F2E7A98 + +``` + +#### From PyPI #### +Hold your horses, boy. I haven't finished development, so the packages on +[PyPI](https://pypi.python.org) are still the old versions belonging to the +other authors. + +### Bug Reports & Feature Requests ### +Our bugtracker is [here](https://leap.se/code/projects/eip_server/issue/new). + +Please use that for bug reports and feature requests instead of github's +tracker. We're using github for code commenting and review between +collaborators. diff --git a/TODO b/TODO new file mode 100644 index 0000000..d752f6d --- /dev/null +++ b/TODO @@ -0,0 +1,60 @@ +-*- mode: org -*- + +* Keyring separation :keyseparation: +** TODO in GPG.gen_key() :keyseparation:gen_key: +It would be nice to have an option for gen_key() [[gnupg.py:927]] to +automatically switch before key generation to a new tempfile.mkdtemp() +directory, with a new keyring and secring, and then to rename either the +directory or the keyrings with the long keyid of the key which was freshly +generated. + +* I/O :io: +** TODO in GPG.__make_args() :io:makeargs: +It would be nice to make the file descriptors for communication with the GnuPG +process configurable, and not the default, hard-coded 0=stdin 1=stdout +2=stderr. + +* Key editing :editkey: +** TODO add '--edit-key' feature :editkey: +see :compatibility:gen__key_input: + +* Compatibility between GnuPG versions :compatibility: +** TODO GnuPG>=2.1.0 won't allow key generation with preset passphrase +*** TODO in GPG.gen__key_input() :compatibility:gen_key_input: +In the docstring of GPG.gen__key_input() [[gnupg.py:1068]], for the parameter +'passphrase', it is explained that: + + :param str passphrase: The passphrase for the new key. The default is + to not use any passphrase. Note that + GnuPG>=2.1.x will not allow you to specify a + passphrase for batch key generation -- GnuPG + will ignore the ``passphrase`` parameter, stop, + and ask the user for the new passphrase. + However, we can put the command '%no-protection' + into the batch key generation file to allow a + passwordless key to be created, which can then + have its passphrase set later with '--edit-key'. + +If we add a GnuPG version detection feature (the version string is already +obtained in GPG.___init___() [[gnupg.py:407]]), then we can automatically chain +GPG.gen__key_input() to another new feature for '--edit-key'. This chaining +would likely need to happen here [[gnupg.py:1146]]. + +*** TODO add '--edit-key' feature :editkey: +This would be necessary for adding a passphrase to the key after passwordless +generation in GnuPG>=2.1.0. + +* Code cleanup :cleanup: +** TODO in parsers.__sanitise() :cleanup:sanitise: +Ughh...this is the ugliest code I think I've ever written. It works, but I +worry that it is fragile, not to mention *I* have trouble reading it, and I +fucking wrote the damn thing. There's probably not much that could be done to +make it more Pythonic, because type checks and input validation are pretty much +intrinsically non-Pythonic. But did i mention that it's ugly? I'm sure these +functions would be pretty glad to get a shower, shave, and haircut. + +** TODO in parsers.__is_allowed() :cleanup:is_allowed: +There is a lot of madness dealing with stupid things like hyphens +vs. underscores, and lists of options vs. strings. This can *definitely* be +cleaned up. + diff --git a/docs/DETAILS b/docs/DETAILS new file mode 100644 index 0000000..d5c5cea --- /dev/null +++ b/docs/DETAILS @@ -0,0 +1,1225 @@ +# doc/DETAILS -*- org -*- +#+TITLE: GnuPG Details +# Globally disable superscripts and subscripts: +#+OPTIONS: ^:{} +# + +# Note: This file uses org-mode; it should be easy to read as plain +# text but be aware of some markup peculiarities: Verbatim code is +# enclosed in #+begin-example, #+end-example blocks or marked by a +# colon as the first non-white-space character, words bracketed with +# equal signs indicate a monospace font, and the usual /italics/, +# *bold*, and _underline_ conventions are recognized. + +This is the DETAILS file for GnuPG which specifies some internals and +parts of the external API for GPG and GPGSM. + +* Format of the colon listings + The format is a based on colon separated record, each recods starts + with a tag string and extends to the end of the line. Here is an + example: +#+begin_example +$ gpg --with-colons --list-keys \ + --with-fingerprint --with-fingerprint wk@gnupg.org +pub:f:1024:17:6C7EE1B8621CC013:899817715:1055898235::m:::scESC: +fpr:::::::::ECAF7590EB3443B5C7CF3ACB6C7EE1B8621CC013: +uid:f::::::::Werner Koch : +uid:f::::::::Werner Koch : +sub:f:1536:16:06AD222CADF6A6E1:919537416:1036177416:::::e: +fpr:::::::::CF8BCC4B18DE08FCD8A1615906AD222CADF6A6E1: +sub:r:1536:20:5CE086B5B5A18FF4:899817788:1025961788:::::esc: +fpr:::::::::AB059359A3B81F410FCFF97F5CE086B5B5A18FF4: +#+end_example + +The double =--with-fingerprint= prints the fingerprint for the subkeys +too. Old versions of gpg used a lighly different format and required +the use of the option =--fixed-list-mode= to conform to format +described here. + +** Description of the fields +*** Field 1 - Type of record + + - pub :: Public key + - crt :: X.509 certificate + - crs :: X.509 certificate and private key available + - sub :: Subkey (secondary key) + - sec :: Secret key + - ssb :: Secret subkey (secondary key) + - uid :: User id (only field 10 is used). + - uat :: User attribute (same as user id except for field 10). + - sig :: Signature + - rev :: Revocation signature + - fpr :: Fingerprint (fingerprint is in field 10) + - pkd :: Public key data [*] + - grp :: Keygrip + - rvk :: Revocation key + - tru :: Trust database information [*] + - spk :: Signature subpacket [*] + - cfg :: Configuration data [*] + + Records marked with an asterisk are described at [[*Special%20field%20formats][*Special fields]]. + +*** Field 2 - Validity + + This is a letter describing the computed validity of a key. + Currently this is a single letter, but be prepared that additional + information may follow in some future versions. Note that GnuPG < + 2.1 does not set this field for secret key listings. + + - o :: Unknown (this key is new to the system) + - i :: The key is invalid (e.g. due to a missing self-signature) + - d :: The key has been disabled + (deprecated - use the 'D' in field 12 instead) + - r :: The key has been revoked + - e :: The key has expired + - - :: Unknown validity (i.e. no value assigned) + - q :: Undefined validity. '-' and 'q' may safely be treated as + the same value for most purposes + - n :: The key is not valid + - m :: The key is marginal valid. + - f :: The key is fully valid + - u :: The key is ultimately valid. This often means that the + secret key is available, but any key may be marked as + ultimately valid. + - w :: The key has a well known private part. + - s :: The key has special validity. This means that it might be + self-signed and expected to be used in the STEED sytem. + + If the validity information is given for a UID or UAT record, it + describes the validity calculated based on this user ID. If given + for a key record it describes the validity taken from the best + rated user ID. + + For X.509 certificates a 'u' is used for a trusted root + certificate (i.e. for the trust anchor) and an 'f' for all other + valid certificates. + +*** Field 3 - Key length + + The length of key in bits. + +*** Field 4 - Public key algorithm + + The values here are those from the OpenPGP specs or if they are + greather than 255 the algorithm ids as used by Libgcrypt. + +*** Field 5 - KeyID + + This is the 64 bit keyid as specified by OpenPGP and the last 64 + bit of the SHA-1 fingerprint of an X.509 certifciate. + +*** Field 6 - Creation date + + The creation date of the key is given in UTC. For UID and UAT + records, this is used for the self-signature date. Note that the + date is usally printed in seconds since epoch, however, we are + migrating to an ISO 8601 format (e.g. "19660205T091500"). This is + currently only relevant for X.509. A simple way to detect the new + format is to scan for the 'T'. Note that old versions of gpg + without using the =--fixed-list-mode= option used a "yyyy-mm-tt" + format. + +*** Field 7 - Expiration date + + Key or UID/UAT expiration date or empty if it does not expire. + +*** Field 8 - Certificate S/N, UID hash, trust signature info + + Used for serial number in crt records. For UID and UAT records, + this is a hash of the user ID contents used to represent that + exact user ID. For trust signatures, this is the trust depth + seperated by the trust value by a space. + +*** Field 9 - Ownertrust + + This is only used on primary keys. This is a single letter, but + be prepared that additional information may follow in future + versions. For trust signatures with a regular expression, this is + the regular expression value, quoted as in field 10. + +*** Field 10 - User-ID + The value is quoted like a C string to avoid control characters + (the colon is quoted =\x3a=). For a "pub" record this field is + not used on --fixed-list-mode. A UAT record puts the attribute + subpacket count here, a space, and then the total attribute + subpacket size. In gpgsm the issuer name comes here. A FPR + record stores the fingerprint here. The fingerprint of a + revocation key is stored here. +*** Field 11 - Signature class + + Signature class as per RFC-4880. This is a 2 digit hexnumber + followed by either the letter 'x' for an exportable signature or + the letter 'l' for a local-only signature. The class byte of an + revocation key is also given here, 'x' and 'l' is used the same + way. This field if not used for X.509. + +*** Field 12 - Key capabilities + + The defined capabilities are: + + - e :: Encrypt + - s :: Sign + - c :: Certify + - a :: Authentication + - ? :: Unknown capability + + A key may have any combination of them in any order. In addition + to these letters, the primary key has uppercase versions of the + letters to denote the _usable_ capabilities of the entire key, and + a potential letter 'D' to indicate a disabled key. + +*** Field 13 - Issuer certificate fingerprint or other info + + Used in FPR records for S/MIME keys to store the fingerprint of + the issuer certificate. This is useful to build the certificate + path based on certificates stored in the local key database it is + only filled if the issuer certificate is available. The root has + been reached if this is the same string as the fingerprint. The + advantage of using this value is that it is guaranteed to have + been been build by the same lookup algorithm as gpgsm uses. + + For "uid" records this field lists the preferences in the same way + gpg's --edit-key menu does. + + For "sig" records, this is the fingerprint of the key that issued + the signature. Note that this is only filled in if the signature + verified correctly. Note also that for various technical reasons, + this fingerprint is only available if --no-sig-cache is used. + +*** Field 14 - Flag field + + Flag field used in the --edit menu output + +*** Field 15 - S/N of a token + + Used in sec/sbb to print the serial number of a token (internal + protect mode 1002) or a '#' if that key is a simple stub (internal + protect mode 1001) + +*** Field 16 - Hash algorithm + + For sig records, this is the used hash algorithm. For example: + 2 = SHA-1, 8 = SHA-256. + +** Special fields + +*** PKD - Public key data + + If field 1 has the tag "pkd", a listing looks like this: +#+begin_example +pkd:0:1024:B665B1435F4C2 .... FF26ABB: + ! ! !-- the value + ! !------ for information number of bits in the value + !--------- index (eg. DSA goes from 0 to 3: p,q,g,y) +#+end_example + +*** TRU - Trust database information + Example for a "tru" trust base record: +#+begin_example + tru:o:0:1166697654:1:3:1:5 +#+end_example + + - Field 2 :: Reason for staleness of trust. If this field is + empty, then the trustdb is not stale. This field may + have multiple flags in it: + + - o :: Trustdb is old + - t :: Trustdb was built with a different trust model + than the one we are using now. + + - Field 3 :: Trust model + + - 0 :: Classic trust model, as used in PGP 2.x. + - 1 :: PGP trust model, as used in PGP 6 and later. + This is the same as the classic trust model, + except for the addition of trust signatures. + + GnuPG before version 1.4 used the classic trust model + by default. GnuPG 1.4 and later uses the PGP trust + model by default. + + - Field 4 :: Date trustdb was created in seconds since Epoch. + - Field 5 :: Date trustdb will expire in seconds since Epoch. + - Field 6 :: Number of marginally trusted users to introduce a new + key signer (gpg's option --marginals-needed). + - Field 7 :: Number of completely trusted users to introduce a new + key signer. (gpg's option --completes-needed) + + - Field 8 :: Maximum depth of a certification chain. (gpg's option + --max-cert-depth) + +*** SPK - Signature subpacket records + + - Field 2 :: Subpacket number as per RFC-4880 and later. + - Field 3 :: Flags in hex. Currently the only two bits assigned + are 1, to indicate that the subpacket came from the + hashed part of the signature, and 2, to indicate the + subpacket was marked critical. + - Field 4 :: Length of the subpacket. Note that this is the + length of the subpacket, and not the length of field + 5 below. Due to the need for %-encoding, the length + of field 5 may be up to 3x this value. + - Field 5 :: The subpacket data. Printable ASCII is shown as + ASCII, but other values are rendered as %XX where XX + is the hex value for the byte. + +*** CFG - Configuration data + + --list-config outputs information about the GnuPG configuration + for the benefit of frontends or other programs that call GnuPG. + There are several list-config items, all colon delimited like the + rest of the --with-colons output. The first field is always "cfg" + to indicate configuration information. The second field is one of + (with examples): + + - version :: The third field contains the version of GnuPG. + + : cfg:version:1.3.5 + + - pubkey :: The third field contains the public key algorithms + this version of GnuPG supports, separated by + semicolons. The algorithm numbers are as specified in + RFC-4880. Note that in contrast to the --status-fd + interface these are _not_ the Libgcrypt identifiers. + + : cfg:pubkey:1;2;3;16;17 + + - cipher :: The third field contains the symmetric ciphers this + version of GnuPG supports, separated by semicolons. + The cipher numbers are as specified in RFC-4880. + + : cfg:cipher:2;3;4;7;8;9;10 + + - digest :: The third field contains the digest (hash) algorithms + this version of GnuPG supports, separated by + semicolons. The digest numbers are as specified in + RFC-4880. + + : cfg:digest:1;2;3;8;9;10 + + - compress :: The third field contains the compression algorithms + this version of GnuPG supports, separated by + semicolons. The algorithm numbers are as specified + in RFC-4880. + + : cfg:compress:0;1;2;3 + + - group :: The third field contains the name of the group, and the + fourth field contains the values that the group expands + to, separated by semicolons. + + For example, a group of: + : group mynames = paige 0x12345678 joe patti + would result in: + : cfg:group:mynames:patti;joe;0x12345678;paige + + +* Format of the --status-fd output + + Every line is prefixed with "[GNUPG:] ", followed by a keyword with + the type of the status line and some arguments depending on the type + (maybe none); an application should always be prepared to see more + arguments in future versions. + +** General status codes +*** NEWSIG + May be issued right before a signature verification starts. This + is useful to define a context for parsing ERROR status messages. + No arguments are currently defined. + +*** GOODSIG + The signature with the keyid is good. For each signature only one + of the codes GOODSIG, BADSIG, EXPSIG, EXPKEYSIG, REVKEYSIG or + ERRSIG will be emitted. In the past they were used as a marker + for a new signature; new code should use the NEWSIG status + instead. The username is the primary one encoded in UTF-8 and %XX + escaped. The fingerprint may be used instead of the long keyid if + it is available. This is the case with CMS and might eventually + also be available for OpenPGP. + +*** EXPSIG + The signature with the keyid is good, but the signature is + expired. The username is the primary one encoded in UTF-8 and %XX + escaped. The fingerprint may be used instead of the long keyid if + it is available. This is the case with CMS and might eventually + also be available for OpenPGP. + +*** EXPKEYSIG + The signature with the keyid is good, but the signature was made + by an expired key. The username is the primary one encoded in + UTF-8 and %XX escaped. The fingerprint may be used instead of the + long keyid if it is available. This is the case with CMS and + might eventually also be available for OpenPGP. + +*** REVKEYSIG + The signature with the keyid is good, but the signature was made + by a revoked key. The username is the primary one encoded in UTF-8 + and %XX escaped. The fingerprint may be used instead of the long + keyid if it is available. This is the case with CMS and might + eventually also beñ available for OpenPGP. + +*** BADSIG + The signature with the keyid has not been verified okay. The + username is the primary one encoded in UTF-8 and %XX escaped. The + fingerprint may be used instead of the long keyid if it is + available. This is the case with CMS and might eventually also be + available for OpenPGP. + +*** ERRSIG