Hello community,
here is the log from the commit of package python-python-gnupg for
openSUSE:Factory checked in at 2020-08-05 20:30:03
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-python-gnupg (Old)
and /work/SRC/openSUSE:Factory/.python-python-gnupg.new.3592 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-python-gnupg"
Wed Aug 5 20:30:03 2020 rev:9 rq:824526 version:0.4.6
Changes:
--------
--- /work/SRC/openSUSE:Factory/python-python-gnupg/python-python-gnupg.changes
2019-09-11 10:36:15.411281183 +0200
+++
/work/SRC/openSUSE:Factory/.python-python-gnupg.new.3592/python-python-gnupg.changes
2020-08-05 20:30:15.347125442 +0200
@@ -1,0 +2,9 @@
+Wed Aug 5 13:20:26 UTC 2020 - Marketa Calabkova <[email protected]>
+
+- Update to 0.4.6
+ * Fixed #128: Added ECC support by changing key generation parameters. (The
Key-Length
+ value isn't added if a curve is specified.)
+ * More bugfixes.
+ * Support for Python versions 3.5 and under is discontinued, except for
Python 2.7.
+
+-------------------------------------------------------------------
Old:
----
python-gnupg-0.4.5.tar.gz
New:
----
python-gnupg-0.4.6.tar.gz
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ python-python-gnupg.spec ++++++
--- /var/tmp/diff_new_pack.8Ef11b/_old 2020-08-05 20:30:17.179126398 +0200
+++ /var/tmp/diff_new_pack.8Ef11b/_new 2020-08-05 20:30:17.179126398 +0200
@@ -1,7 +1,7 @@
#
# spec file for package python-python-gnupg
#
-# Copyright (c) 2019 SUSE LINUX GmbH, Nuernberg, Germany.
+# Copyright (c) 2020 SUSE LLC
#
# All modifications and additions to the file contributed by third parties
# remain the property of their copyright owners, unless otherwise agreed
@@ -19,7 +19,7 @@
%{?!python_module:%define python_module() python-%{**} python3-%{**}}
%define oldpython python
Name: python-python-gnupg
-Version: 0.4.5
+Version: 0.4.6
Release: 0
Summary: A wrapper for the GNU Privacy Guard (GPG or GnuPG)
License: BSD-3-Clause
++++++ python-gnupg-0.4.5.tar.gz -> python-gnupg-0.4.6.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/python-gnupg-0.4.5/MANIFEST.in
new/python-gnupg-0.4.6/MANIFEST.in
--- old/python-gnupg-0.4.5/MANIFEST.in 1970-01-01 01:00:00.000000000 +0100
+++ new/python-gnupg-0.4.6/MANIFEST.in 2020-04-17 08:50:10.000000000 +0200
@@ -0,0 +1,6 @@
+include LICENSE.txt
+include README.rst
+include test_gnupg.py
+include messages.json
+include test_*ring.gpg
+
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/python-gnupg-0.4.5/PKG-INFO
new/python-gnupg-0.4.6/PKG-INFO
--- old/python-gnupg-0.4.5/PKG-INFO 2019-08-12 18:50:07.000000000 +0200
+++ new/python-gnupg-0.4.6/PKG-INFO 2020-04-17 13:30:43.000000000 +0200
@@ -1,12 +1,14 @@
-Metadata-Version: 1.1
+Metadata-Version: 1.2
Name: python-gnupg
-Version: 0.4.5
+Version: 0.4.6
Summary: A wrapper for the Gnu Privacy Guard (GPG or GnuPG)
Home-page: https://docs.red-dove.com/python-gnupg/
Author: Vinay Sajip
Author-email: [email protected]
+Maintainer: Vinay Sajip
+Maintainer-email: [email protected]
License: Copyright (C) 2008-2019 by Vinay Sajip. All Rights Reserved. See
LICENSE.txt for license.
-Download-URL:
https://pypi.io/packages/source/p/python-gnupg/python-gnupg-0.4.5.tar.gz
+Download-URL:
https://pypi.io/packages/source/p/python-gnupg/python-gnupg-0.4.6.tar.gz
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 :: 5 - Production/Stable
@@ -15,15 +17,9 @@
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.2
-Classifier: Programming Language :: Python :: 3.3
-Classifier: Programming Language :: Python :: 3.4
-Classifier: Programming Language :: Python :: 3.5
Classifier: Programming Language :: Python :: 3.6
Classifier: Programming Language :: Python :: 3.7
+Classifier: Programming Language :: Python :: 3.8
Classifier: Operating System :: OS Independent
Classifier: Topic :: Software Development :: Libraries :: Python Modules
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/python-gnupg-0.4.5/README.rst
new/python-gnupg-0.4.6/README.rst
--- old/python-gnupg-0.4.5/README.rst 2019-08-12 18:47:20.000000000 +0200
+++ new/python-gnupg-0.4.6/README.rst 2020-04-17 10:33:32.000000000 +0200
@@ -64,12 +64,33 @@
.. note:: GCnn refers to an issue nn on Google Code.
-0.4.6 (future)
+0.4.7 (future)
--------------
Released: Not yet.
+0.4.6
+-----
+
+Released: 2020-04-17
+
+* Fixed #122: Updated documentation about gnupghome needing to be an existing
+ directory.
+
+* Fixed #123: Handled error conditions from gpg when calling trust_keys().
+
+* Fixed #124: Avoided an exception being raised when ImportResult.summary()
+ was called after a failed recv_keys().
+
+* Fixed #128: Added ECC support by changing key generation parameters. (The
Key-Length
+ value isn't added if a curve is specified.)
+
+* Fixed #130: Provided a mechanism to provide more complete error messages.
+
+Support for Python versions 3.5 and under is discontinued, except for Python
2.7.
+
+
0.4.5
-----
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/python-gnupg-0.4.5/gnupg.py
new/python-gnupg-0.4.6/gnupg.py
--- old/python-gnupg-0.4.5/gnupg.py 2019-08-12 18:47:20.000000000 +0200
+++ new/python-gnupg-0.4.6/gnupg.py 2020-04-17 10:35:35.000000000 +0200
@@ -32,9 +32,9 @@
A unittest harness (test_gnupg.py) has also been added.
"""
-__version__ = "0.4.5"
+__version__ = "0.4.6"
__author__ = "Vinay Sajip"
-__date__ = "$12-Aug-2019 15:58:03$"
+__date__ = "$17-Apr-2020 09:35:35$"
try:
from io import StringIO
@@ -349,17 +349,20 @@
# write to "/etc/foo" as a non-root user, a "permission denied"
# error will be sent as a non-status message.
message = 'error - %s' % value
- parts = value.split()
- if parts[-1].isdigit():
- code = int(parts[-1])
- system_error = bool(code & 0x8000)
- code = code & 0x7FFF
- if system_error:
- mapping = self.GPG_SYSTEM_ERROR_CODES
+ operation, code = value.rsplit(' ', 1)
+ if code.isdigit():
+ code = int(code) & 0xFFFFFF # lose the error source
+ if self.gpg.error_map and code in self.gpg.error_map:
+ message = '%s: %s' % (operation,
self.gpg.error_map[code])
else:
- mapping = self.GPG_ERROR_CODES
- if code in mapping:
- message = mapping[code]
+ system_error = bool(code & 0x8000)
+ code = code & 0x7FFF
+ if system_error:
+ mapping = self.GPG_SYSTEM_ERROR_CODES
+ else:
+ mapping = self.GPG_ERROR_CODES
+ if code in mapping:
+ message = '%s: %s' % (operation, mapping[code])
if not self.status:
self.status = message
elif key in ("DECRYPTION_INFO", "PLAINTEXT", "PLAINTEXT_LENGTH",
@@ -376,11 +379,10 @@
sec_dups not_imported'''.split()
def __init__(self, gpg):
self.gpg = gpg
- self.imported = []
self.results = []
self.fingerprints = []
for result in self.counts:
- setattr(self, result, None)
+ setattr(self, result, 0)
def __nonzero__(self):
if self.not_imported: return False
@@ -450,11 +452,11 @@
logger.debug('message ignored: %s, %s', key, value)
def summary(self):
- l = []
- l.append('%d imported' % self.imported)
+ result = []
+ result.append('%d imported' % self.imported)
if self.not_imported: # pragma: no cover
- l.append('%d not imported' % self.not_imported)
- return ', '.join(l)
+ result.append('%d not imported' % self.not_imported)
+ return ', '.join(result)
ESCAPE_PATTERN = re.compile(r'\\x([0-9a-f][0-9a-f])', re.I)
BASIC_ESCAPES = {
@@ -737,6 +739,10 @@
__bool__ = __nonzero__
+class TrustResult(DeleteResult):
+ pass
+
+
class Sign(TextHandler):
"Handle status messages for --sign"
def __init__(self, gpg):
@@ -779,6 +785,8 @@
class GPG(object):
+ error_map = None
+
decode_errors = 'strict'
result_map = {
@@ -791,6 +799,7 @@
'scan': ScanKeys,
'search': SearchKeys,
'sign': Sign,
+ 'trust': TrustResult,
'verify': Verify,
'export': ExportResult,
}
@@ -990,7 +999,8 @@
rr.start()
stdout = process.stdout
- dr = threading.Thread(target=self._read_data, args=(stdout, result,
self.on_data))
+ dr = threading.Thread(target=self._read_data, args=(stdout, result,
+ self.on_data))
dr.setDaemon(True)
logger.debug('stdout reader: %r', dr)
dr.start()
@@ -1000,8 +1010,9 @@
if writer is not None:
writer.join()
process.wait()
- if process.returncode != 0:
- logger.warning('gpg returned a non-zero error code: %d',
process.returncode)
+ rc = process.returncode
+ if rc != 0:
+ logger.warning('gpg returned a non-zero error code: %d', rc)
if stdin is not None:
try:
stdin.close()
@@ -1456,7 +1467,8 @@
if str(val).strip(): # skip empty strings
parms[key] = val
parms.setdefault('Key-Type','RSA')
- parms.setdefault('Key-Length',2048)
+ if 'key_curve' not in kwargs:
+ parms.setdefault('Key-Length',2048)
parms.setdefault('Name-Real', "Autogenerated Key")
logname = (os.environ.get('LOGNAME') or os.environ.get('USERNAME') or
'unspecified')
@@ -1623,9 +1635,12 @@
logger.debug('writing ownertrust info: %s', s);
os.write(fd, s.encode(self.encoding))
os.close(fd)
- result = self.result_map['delete'](self)
+ result = self.result_map['trust'](self)
p = self._open_subprocess(['--import-ownertrust', fn])
self._collect_output(p, result, stdin=p.stdin)
+ if p.returncode != 0:
+ raise ValueError('gpg returned an error - return code %d' %
+ p.returncode)
finally:
os.remove(fn)
return result
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/python-gnupg-0.4.5/messages.json
new/python-gnupg-0.4.6/messages.json
--- old/python-gnupg-0.4.5/messages.json 1970-01-01 01:00:00.000000000
+0100
+++ new/python-gnupg-0.4.6/messages.json 2020-04-17 08:02:24.000000000
+0200
@@ -0,0 +1,565 @@
+{
+ "0000": "Success",
+ "0001": "General error",
+ "0002": "Unknown packet",
+ "0003": "Unknown version in packet",
+ "0004": "Invalid public key algorithm",
+ "0005": "Invalid digest algorithm",
+ "0006": "Bad public key",
+ "0007": "Bad secret key",
+ "0008": "Bad signature",
+ "0009": "No public key",
+ "000A": "Checksum error",
+ "000B": "Bad passphrase",
+ "000C": "Invalid cipher algorithm",
+ "000D": "Cannot open keyring",
+ "000E": "Invalid packet",
+ "000F": "Invalid armor",
+ "0010": "No user ID",
+ "0011": "No secret key",
+ "0012": "Wrong secret key used",
+ "0013": "Bad session key",
+ "0014": "Unknown compression algorithm",
+ "0015": "Number is not prime",
+ "0016": "Invalid encoding method",
+ "0017": "Invalid encryption scheme",
+ "0018": "Invalid signature scheme",
+ "0019": "Invalid attribute",
+ "001A": "No value",
+ "001B": "Not found",
+ "001C": "Value not found",
+ "001D": "Syntax error",
+ "001E": "Bad MPI value",
+ "001F": "Invalid passphrase",
+ "0020": "Invalid signature class",
+ "0021": "Resources exhausted",
+ "0022": "Invalid keyring",
+ "0023": "Trust DB error",
+ "0024": "Bad certificate",
+ "0025": "Invalid user ID",
+ "0026": "Unexpected error",
+ "0027": "Time conflict",
+ "0028": "Keyserver error",
+ "0029": "Wrong public key algorithm",
+ "002A": "Tribute to D. A.",
+ "002B": "Weak encryption key",
+ "002C": "Invalid key length",
+ "002D": "Invalid argument",
+ "002E": "Syntax error in URI",
+ "002F": "Invalid URI",
+ "0030": "Network error",
+ "0031": "Unknown host",
+ "0032": "Selftest failed",
+ "0033": "Data not encrypted",
+ "0034": "Data not processed",
+ "0035": "Unusable public key",
+ "0036": "Unusable secret key",
+ "0037": "Invalid value",
+ "0038": "Bad certificate chain",
+ "0039": "Missing certificate",
+ "003A": "No data",
+ "003B": "Bug",
+ "003C": "Not supported",
+ "003D": "Invalid operation code",
+ "003E": "Timeout",
+ "003F": "Internal error",
+ "0040": "EOF (gcrypt)",
+ "0041": "Invalid object",
+ "0042": "Provided object is too short",
+ "0043": "Provided object is too large",
+ "0044": "Missing item in object",
+ "0045": "Not implemented",
+ "0046": "Conflicting use",
+ "0047": "Invalid cipher mode",
+ "0048": "Invalid flag",
+ "0049": "Invalid handle",
+ "004A": "Result truncated",
+ "004B": "Incomplete line",
+ "004C": "Invalid response",
+ "004D": "No agent running",
+ "004E": "Agent error",
+ "004F": "Invalid data",
+ "0050": "Unspecific Assuan server fault",
+ "0051": "General Assuan error",
+ "0052": "Invalid session key",
+ "0053": "Invalid S-expression",
+ "0054": "Unsupported algorithm",
+ "0055": "No pinentry",
+ "0056": "pinentry error",
+ "0057": "Bad PIN",
+ "0058": "Invalid name",
+ "0059": "Bad data",
+ "005A": "Invalid parameter",
+ "005B": "Wrong card",
+ "005C": "No dirmngr",
+ "005D": "dirmngr error",
+ "005E": "Certificate revoked",
+ "005F": "No CRL known",
+ "0060": "CRL too old",
+ "0061": "Line too long",
+ "0062": "Not trusted",
+ "0063": "Operation cancelled",
+ "0064": "Bad CA certificate",
+ "0065": "Certificate expired",
+ "0066": "Certificate too young",
+ "0067": "Unsupported certificate",
+ "0068": "Unknown S-expression",
+ "0069": "Unsupported protection",
+ "006A": "Corrupted protection",
+ "006B": "Ambiguous name",
+ "006C": "Card error",
+ "006D": "Card reset required",
+ "006E": "Card removed",
+ "006F": "Invalid card",
+ "0070": "Card not present",
+ "0071": "No PKCS15 application",
+ "0072": "Not confirmed",
+ "0073": "Configuration error",
+ "0074": "No policy match",
+ "0075": "Invalid index",
+ "0076": "Invalid ID",
+ "0077": "No SmartCard daemon",
+ "0078": "SmartCard daemon error",
+ "0079": "Unsupported protocol",
+ "007A": "Bad PIN method",
+ "007B": "Card not initialized",
+ "007C": "Unsupported operation",
+ "007D": "Wrong key usage",
+ "007E": "Nothing found",
+ "007F": "Wrong blob type",
+ "0080": "Missing value",
+ "0081": "Hardware problem",
+ "0082": "PIN blocked",
+ "0083": "Conditions of use not satisfied",
+ "0084": "PINs are not synced",
+ "0085": "Invalid CRL",
+ "0086": "BER error",
+ "0087": "Invalid BER",
+ "0088": "Element not found",
+ "0089": "Identifier not found",
+ "008A": "Invalid tag",
+ "008B": "Invalid length",
+ "008C": "Invalid key info",
+ "008D": "Unexpected tag",
+ "008E": "Not DER encoded",
+ "008F": "No CMS object",
+ "0090": "Invalid CMS object",
+ "0091": "Unknown CMS object",
+ "0092": "Unsupported CMS object",
+ "0093": "Unsupported encoding",
+ "0094": "Unsupported CMS version",
+ "0095": "Unknown algorithm",
+ "0096": "Invalid crypto engine",
+ "0097": "Public key not trusted",
+ "0098": "Decryption failed",
+ "0099": "Key expired",
+ "009A": "Signature expired",
+ "009B": "Encoding problem",
+ "009C": "Invalid state",
+ "009D": "Duplicated value",
+ "009E": "Missing action",
+ "009F": "ASN.1 module not found",
+ "00A0": "Invalid OID string",
+ "00A1": "Invalid time",
+ "00A2": "Invalid CRL object",
+ "00A3": "Unsupported CRL version",
+ "00A4": "Invalid certificate object",
+ "00A5": "Unknown name",
+ "00A6": "A locale function failed",
+ "00A7": "Not locked",
+ "00A8": "Protocol violation",
+ "00A9": "Invalid MAC",
+ "00AA": "Invalid request",
+ "00AB": "Unknown extension",
+ "00AC": "Unknown critical extension",
+ "00AD": "Locked",
+ "00AE": "Unknown option",
+ "00AF": "Unknown command",
+ "00B0": "Not operational",
+ "00B1": "No passphrase given",
+ "00B2": "No PIN given",
+ "00B3": "Not enabled",
+ "00B4": "No crypto engine",
+ "00B5": "Missing key",
+ "00B6": "Too many objects",
+ "00B7": "Limit reached",
+ "00B8": "Not initialized",
+ "00B9": "Missing issuer certificate",
+ "00BA": "No keyserver available",
+ "00BB": "Invalid elliptic curve",
+ "00BC": "Unknown elliptic curve",
+ "00BD": "Duplicated key",
+ "00BE": "Ambiguous result",
+ "00BF": "No crypto context",
+ "00C0": "Wrong crypto context",
+ "00C1": "Bad crypto context",
+ "00C2": "Conflict in the crypto context",
+ "00C3": "Broken public key",
+ "00C4": "Broken secret key",
+ "00C5": "Invalid MAC algorithm",
+ "00C6": "Operation fully cancelled",
+ "00C7": "Operation not yet finished",
+ "00C8": "Buffer too short",
+ "00C9": "Invalid length specifier in S-expression",
+ "00CA": "String too long in S-expression",
+ "00CB": "Unmatched parentheses in S-expression",
+ "00CC": "S-expression not canonical",
+ "00CD": "Bad character in S-expression",
+ "00CE": "Bad quotation in S-expression",
+ "00CF": "Zero prefix in S-expression",
+ "00D0": "Nested display hints in S-expression",
+ "00D1": "Unmatched display hints",
+ "00D2": "Unexpected reserved punctuation in S-expression",
+ "00D3": "Bad hexadecimal character in S-expression",
+ "00D4": "Odd hexadecimal numbers in S-expression",
+ "00D5": "Bad octal character in S-expression",
+ "00D9": "All subkeys are expired or revoked",
+ "00DA": "Database is corrupted",
+ "00DB": "Server indicated a failure",
+ "00DC": "No name",
+ "00DD": "No key",
+ "00DE": "Legacy key",
+ "00DF": "Request too short",
+ "00E0": "Request too long",
+ "00E1": "Object is in termination state",
+ "00E2": "No certificate chain",
+ "00E3": "Certificate is too large",
+ "00E4": "Invalid record",
+ "00E5": "The MAC does not verify",
+ "00E6": "Unexpected message",
+ "00E7": "Compression or decompression failed",
+ "00E8": "A counter would wrap",
+ "00E9": "Fatal alert message received",
+ "00EA": "No cipher algorithm",
+ "00EB": "Missing client certificate",
+ "00EC": "Close notification received",
+ "00ED": "Ticket expired",
+ "00EE": "Bad ticket",
+ "00EF": "Unknown identity",
+ "00F0": "Bad certificate message in handshake",
+ "00F1": "Bad certificate request message in handshake",
+ "00F2": "Bad certificate verify message in handshake",
+ "00F3": "Bad change cipher message in handshake",
+ "00F4": "Bad client hello message in handshake",
+ "00F5": "Bad server hello message in handshake",
+ "00F6": "Bad server hello done message in handshake",
+ "00F7": "Bad finished message in handshake",
+ "00F8": "Bad server key exchange message in handshake",
+ "00F9": "Bad client key exchange message in handshake",
+ "00FA": "Bogus string",
+ "00FB": "Forbidden",
+ "00FC": "Key disabled",
+ "00FD": "Not possible with a card based key",
+ "00FE": "Invalid lock object",
+ "00FF": "True",
+ "0100": "False",
+ "0101": "General IPC error",
+ "0102": "IPC accept call failed",
+ "0103": "IPC connect call failed",
+ "0104": "Invalid IPC response",
+ "0105": "Invalid value passed to IPC",
+ "0106": "Incomplete line passed to IPC",
+ "0107": "Line passed to IPC too long",
+ "0108": "Nested IPC commands",
+ "0109": "No data callback in IPC",
+ "010A": "No inquire callback in IPC",
+ "010B": "Not an IPC server",
+ "010C": "Not an IPC client",
+ "010D": "Problem starting IPC server",
+ "010E": "IPC read error",
+ "010F": "IPC write error",
+ "0111": "Too much data for IPC layer",
+ "0112": "Unexpected IPC command",
+ "0113": "Unknown IPC command",
+ "0114": "IPC syntax error",
+ "0115": "IPC call has been cancelled",
+ "0116": "No input source for IPC",
+ "0117": "No output source for IPC",
+ "0118": "IPC parameter error",
+ "0119": "Unknown IPC inquire",
+ "012C": "Crypto engine too old",
+ "012D": "Screen or window too small",
+ "012E": "Screen or window too large",
+ "012F": "Required environment variable not set",
+ "0130": "User ID already exists",
+ "0131": "Name already exists",
+ "0132": "Duplicated name",
+ "0133": "Object is too young",
+ "0134": "Object is too old",
+ "0135": "Unknown flag",
+ "0136": "Invalid execution order",
+ "0137": "Already fetched",
+ "0138": "Try again later",
+ "0139": "Wrong name",
+ "013A": "Not authenticated",
+ "013B": "Bad authentication",
+ "013C": "No Keybox daemon running",
+ "013D": "Keybox daemon error",
+ "013E": "Service is not running",
+ "013F": "Service error",
+ "029A": "System bug detected",
+ "02C7": "Unknown DNS error",
+ "02C8": "Invalid DNS section",
+ "02C9": "Invalid textual address form",
+ "02CA": "Missing DNS query packet",
+ "02CB": "Missing DNS answer packet",
+ "02CC": "Connection closed in DNS",
+ "02CD": "Verification failed in DNS",
+ "02CE": "DNS Timeout",
+ "02D1": "General LDAP error",
+ "02D2": "General LDAP attribute error",
+ "02D3": "General LDAP name error",
+ "02D4": "General LDAP security error",
+ "02D5": "General LDAP service error",
+ "02D6": "General LDAP update error",
+ "02D7": "Experimental LDAP error code",
+ "02D8": "Private LDAP error code",
+ "02D9": "Other general LDAP error",
+ "02EE": "LDAP connecting failed (X)",
+ "02EF": "LDAP referral limit exceeded",
+ "02F0": "LDAP client loop",
+ "02F2": "No LDAP results returned",
+ "02F3": "LDAP control not found",
+ "02F4": "Not supported by LDAP",
+ "02F5": "LDAP connect error",
+ "02F6": "Out of memory in LDAP",
+ "02F7": "Bad parameter to an LDAP routine",
+ "02F8": "User cancelled LDAP operation",
+ "02F9": "Bad LDAP search filter",
+ "02FA": "Unknown LDAP authentication method",
+ "02FB": "Timeout in LDAP",
+ "02FC": "LDAP decoding error",
+ "02FD": "LDAP encoding error",
+ "02FE": "LDAP local error",
+ "02FF": "Cannot contact LDAP server",
+ "0300": "LDAP success",
+ "0301": "LDAP operations error",
+ "0302": "LDAP protocol error",
+ "0303": "Time limit exceeded in LDAP",
+ "0304": "Size limit exceeded in LDAP",
+ "0305": "LDAP compare false",
+ "0306": "LDAP compare true",
+ "0307": "LDAP authentication method not supported",
+ "0308": "Strong(er) LDAP authentication required",
+ "0309": "Partial LDAP results+referral received",
+ "030A": "LDAP referral",
+ "030B": "Administrative LDAP limit exceeded",
+ "030C": "Critical LDAP extension is unavailable",
+ "030D": "Confidentiality required by LDAP",
+ "030E": "LDAP SASL bind in progress",
+ "0310": "No such LDAP attribute",
+ "0311": "Undefined LDAP attribute type",
+ "0312": "Inappropriate matching in LDAP",
+ "0313": "Constraint violation in LDAP",
+ "0314": "LDAP type or value exists",
+ "0315": "Invalid syntax in LDAP",
+ "0320": "No such LDAP object",
+ "0321": "LDAP alias problem",
+ "0322": "Invalid DN syntax in LDAP",
+ "0323": "LDAP entry is a leaf",
+ "0324": "LDAP alias dereferencing problem",
+ "032F": "LDAP proxy authorization failure (X)",
+ "0330": "Inappropriate LDAP authentication",
+ "0331": "Invalid LDAP credentials",
+ "0332": "Insufficient access for LDAP",
+ "0333": "LDAP server is busy",
+ "0334": "LDAP server is unavailable",
+ "0335": "LDAP server is unwilling to perform",
+ "0336": "Loop detected by LDAP",
+ "0340": "LDAP naming violation",
+ "0341": "LDAP object class violation",
+ "0342": "LDAP operation not allowed on non-leaf",
+ "0343": "LDAP operation not allowed on RDN",
+ "0344": "Already exists (LDAP)",
+ "0345": "Cannot modify LDAP object class",
+ "0346": "LDAP results too large",
+ "0347": "LDAP operation affects multiple DSAs",
+ "034C": "Virtual LDAP list view error",
+ "0350": "Other LDAP error",
+ "0371": "Resources exhausted in LCUP",
+ "0372": "Security violation in LCUP",
+ "0373": "Invalid data in LCUP",
+ "0374": "Unsupported scheme in LCUP",
+ "0375": "Reload required in LCUP",
+ "0376": "LDAP cancelled",
+ "0377": "No LDAP operation to cancel",
+ "0378": "Too late to cancel LDAP",
+ "0379": "Cannot cancel LDAP",
+ "037A": "LDAP assertion failed",
+ "037B": "Proxied authorization denied by LDAP",
+ "0400": "User defined error code 1",
+ "0401": "User defined error code 2",
+ "0402": "User defined error code 3",
+ "0403": "User defined error code 4",
+ "0404": "User defined error code 5",
+ "0405": "User defined error code 6",
+ "0406": "User defined error code 7",
+ "0407": "User defined error code 8",
+ "0408": "User defined error code 9",
+ "0409": "User defined error code 10",
+ "040A": "User defined error code 11",
+ "040B": "User defined error code 12",
+ "040C": "User defined error code 13",
+ "040D": "User defined error code 14",
+ "040E": "User defined error code 15",
+ "040F": "User defined error code 16",
+ "05DC": "SQL success",
+ "05DD": "SQL error",
+ "05DE": "Internal logic error in SQL library",
+ "05DF": "Access permission denied (SQL)",
+ "05E0": "SQL abort was requested",
+ "05E1": "SQL database file is locked",
+ "05E2": "An SQL table in the database is locked",
+ "05E3": "SQL library ran out of core",
+ "05E4": "Attempt to write a readonly SQL database",
+ "05E5": "SQL operation terminated by interrupt",
+ "05E6": "I/O error during SQL operation",
+ "05E7": "SQL database disk image is malformed",
+ "05E8": "Unknown opcode in SQL file control",
+ "05E9": "Insertion failed because SQL database is full",
+ "05EA": "Unable to open the SQL database file",
+ "05EB": "SQL database lock protocol error",
+ "05EC": "(internal SQL code: empty)",
+ "05ED": "SQL database schema changed",
+ "05EE": "String or blob exceeds size limit (SQL)",
+ "05EF": "SQL abort due to constraint violation",
+ "05F0": "Data type mismatch (SQL)",
+ "05F1": "SQL library used incorrectly",
+ "05F2": "SQL library uses unsupported OS features",
+ "05F3": "Authorization denied (SQL)",
+ "05F4": "(unused SQL code: format)",
+ "05F5": "SQL bind parameter out of range",
+ "05F6": "File opened that is not an SQL database file",
+ "05F7": "Notifications from SQL logger",
+ "05F8": "Warnings from SQL logger",
+ "0640": "SQL has another row ready",
+ "0641": "SQL has finished executing",
+ "3FFD": "System error w/o errno",
+ "3FFF": "End of file",
+ "8000": "Argument list too long",
+ "8001": "Permission denied",
+ "8002": "Address already in use",
+ "8003": "Cannot assign requested address",
+ "8004": "Advertise error",
+ "8005": "Address family not supported by protocol",
+ "8006": "Resource temporarily unavailable",
+ "8007": "Operation already in progress",
+ "800A": "Invalid exchange",
+ "800B": "Bad file descriptor",
+ "800C": "File descriptor in bad state",
+ "800D": "Bad message",
+ "800E": "Invalid request descriptor",
+ "8010": "Invalid request code",
+ "8011": "Invalid slot",
+ "8012": "Bad font file format",
+ "8013": "Device or resource busy",
+ "8014": "Operation canceled",
+ "8015": "No child processes",
+ "8016": "Channel number out of range",
+ "8017": "Communication error on send",
+ "8018": "Software caused connection abort",
+ "8019": "Connection refused",
+ "801A": "Connection reset by peer",
+ "801C": "Resource deadlock avoided",
+ "801D": "Resource deadlock avoided",
+ "801E": "Destination address required",
+ "8020": "Numerical argument out of domain",
+ "8021": "RFS specific error",
+ "8022": "Disk quota exceeded",
+ "8023": "File exists",
+ "8024": "Bad address",
+ "8025": "File too large",
+ "8029": "Host is down",
+ "802A": "No route to host",
+ "802B": "Identifier removed",
+ "802D": "Invalid or incomplete multibyte or wide character",
+ "802E": "Operation now in progress",
+ "802F": "Interrupted system call",
+ "8030": "Invalid argument",
+ "8031": "Input/output error",
+ "8032": "Transport endpoint is already connected",
+ "8033": "Is a directory",
+ "8034": "Is a named type file",
+ "8035": "Level 2 halted",
+ "8036": "Level 2 not synchronized",
+ "8037": "Level 3 halted",
+ "8038": "Level 3 reset",
+ "8039": "Can not access a needed shared library",
+ "803A": "Accessing a corrupted shared library",
+ "803B": "Cannot exec a shared library directly",
+ "803C": "Attempting to link in too many shared libraries",
+ "803D": ".lib section in a.out corrupted",
+ "803E": "Link number out of range",
+ "803F": "Too many levels of symbolic links",
+ "8040": "Wrong medium type",
+ "8041": "Too many open files",
+ "8042": "Too many links",
+ "8043": "Message too long",
+ "8044": "Multihop attempted",
+ "8045": "File name too long",
+ "8046": "No XENIX semaphores available",
+ "8048": "Network is down",
+ "8049": "Network dropped connection on reset",
+ "804A": "Network is unreachable",
+ "804B": "Too many open files in system",
+ "804C": "No anode",
+ "804D": "No buffer space available",
+ "804E": "No CSI structure available",
+ "804F": "No data available",
+ "8050": "No such device",
+ "8051": "No such file or directory",
+ "8052": "Exec format error",
+ "8053": "No locks available",
+ "8054": "Link has been severed",
+ "8055": "No medium found",
+ "8056": "Cannot allocate memory",
+ "8057": "No message of desired type",
+ "8058": "Machine is not on the network",
+ "8059": "Package not installed",
+ "805A": "Protocol not available",
+ "805B": "No space left on device",
+ "805C": "Out of streams resources",
+ "805D": "Device not a stream",
+ "805E": "Function not implemented",
+ "805F": "Block device required",
+ "8060": "Transport endpoint is not connected",
+ "8061": "Not a directory",
+ "8062": "Directory not empty",
+ "8063": "Not a XENIX named type file",
+ "8064": "Socket operation on non-socket",
+ "8065": "Operation not supported",
+ "8066": "Inappropriate ioctl for device",
+ "8067": "Name not unique on network",
+ "8068": "No such device or address",
+ "8069": "Operation not supported",
+ "806A": "Value too large for defined data type",
+ "806B": "Operation not permitted",
+ "806C": "Protocol family not supported",
+ "806D": "Broken pipe",
+ "8072": "Protocol error",
+ "8073": "Protocol not supported",
+ "8074": "Protocol wrong type for socket",
+ "8075": "Numerical result out of range",
+ "8076": "Remote address changed",
+ "8077": "Object is remote",
+ "8078": "Remote I/O error",
+ "8079": "Interrupted system call should be restarted",
+ "807A": "Read-only file system",
+ "807C": "Cannot send after transport endpoint shutdown",
+ "807D": "Socket type not supported",
+ "807E": "Illegal seek",
+ "807F": "No such process",
+ "8080": "Srmount error",
+ "8081": "Stale file handle",
+ "8082": "Streams pipe error",
+ "8083": "Timer expired",
+ "8084": "Connection timed out",
+ "8085": "Too many references: cannot splice",
+ "8086": "Text file busy",
+ "8087": "Structure needs cleaning",
+ "8088": "Protocol driver not attached",
+ "8089": "Too many users",
+ "808A": "Resource temporarily unavailable",
+ "808B": "Invalid cross-device link",
+ "808C": "Exchange full"
+}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/python-gnupg-0.4.5/python_gnupg.egg-info/PKG-INFO
new/python-gnupg-0.4.6/python_gnupg.egg-info/PKG-INFO
--- old/python-gnupg-0.4.5/python_gnupg.egg-info/PKG-INFO 1970-01-01
01:00:00.000000000 +0100
+++ new/python-gnupg-0.4.6/python_gnupg.egg-info/PKG-INFO 2020-04-17
13:30:43.000000000 +0200
@@ -0,0 +1,25 @@
+Metadata-Version: 1.2
+Name: python-gnupg
+Version: 0.4.6
+Summary: A wrapper for the Gnu Privacy Guard (GPG or GnuPG)
+Home-page: https://docs.red-dove.com/python-gnupg/
+Author: Vinay Sajip
+Author-email: [email protected]
+Maintainer: Vinay Sajip
+Maintainer-email: [email protected]
+License: Copyright (C) 2008-2019 by Vinay Sajip. All Rights Reserved. See
LICENSE.txt for license.
+Download-URL:
https://pypi.io/packages/source/p/python-gnupg/python-gnupg-0.4.6.tar.gz
+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 :: 5 - Production/Stable
+Classifier: Intended Audience :: Developers
+Classifier: License :: OSI Approved :: BSD License
+Classifier: Programming Language :: Python
+Classifier: Programming Language :: Python :: 2
+Classifier: Programming Language :: Python :: 3
+Classifier: Programming Language :: Python :: 2.7
+Classifier: Programming Language :: Python :: 3.6
+Classifier: Programming Language :: Python :: 3.7
+Classifier: Programming Language :: Python :: 3.8
+Classifier: Operating System :: OS Independent
+Classifier: Topic :: Software Development :: Libraries :: Python Modules
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/python-gnupg-0.4.5/python_gnupg.egg-info/SOURCES.txt
new/python-gnupg-0.4.6/python_gnupg.egg-info/SOURCES.txt
--- old/python-gnupg-0.4.5/python_gnupg.egg-info/SOURCES.txt 1970-01-01
01:00:00.000000000 +0100
+++ new/python-gnupg-0.4.6/python_gnupg.egg-info/SOURCES.txt 2020-04-17
13:30:43.000000000 +0200
@@ -0,0 +1,14 @@
+LICENSE.txt
+MANIFEST.in
+README.rst
+gnupg.py
+messages.json
+setup.cfg
+setup.py
+test_gnupg.py
+test_pubring.gpg
+test_secring.gpg
+python_gnupg.egg-info/PKG-INFO
+python_gnupg.egg-info/SOURCES.txt
+python_gnupg.egg-info/dependency_links.txt
+python_gnupg.egg-info/top_level.txt
\ No newline at end of file
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/python-gnupg-0.4.5/python_gnupg.egg-info/dependency_links.txt
new/python-gnupg-0.4.6/python_gnupg.egg-info/dependency_links.txt
--- old/python-gnupg-0.4.5/python_gnupg.egg-info/dependency_links.txt
1970-01-01 01:00:00.000000000 +0100
+++ new/python-gnupg-0.4.6/python_gnupg.egg-info/dependency_links.txt
2020-04-17 13:30:43.000000000 +0200
@@ -0,0 +1 @@
+
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/python-gnupg-0.4.5/python_gnupg.egg-info/top_level.txt
new/python-gnupg-0.4.6/python_gnupg.egg-info/top_level.txt
--- old/python-gnupg-0.4.5/python_gnupg.egg-info/top_level.txt 1970-01-01
01:00:00.000000000 +0100
+++ new/python-gnupg-0.4.6/python_gnupg.egg-info/top_level.txt 2020-04-17
13:30:43.000000000 +0200
@@ -0,0 +1 @@
+gnupg
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/python-gnupg-0.4.5/setup.cfg
new/python-gnupg-0.4.6/setup.cfg
--- old/python-gnupg-0.4.5/setup.cfg 1970-01-01 01:00:00.000000000 +0100
+++ new/python-gnupg-0.4.6/setup.cfg 2020-04-17 13:30:43.000000000 +0200
@@ -0,0 +1,7 @@
+[bdist_wheel]
+universal = 1
+
+[egg_info]
+tag_build =
+tag_date = 0
+
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/python-gnupg-0.4.5/setup.py
new/python-gnupg-0.4.6/setup.py
--- old/python-gnupg-0.4.5/setup.py 2019-07-16 09:21:35.000000000 +0200
+++ new/python-gnupg-0.4.6/setup.py 2020-04-17 13:29:40.000000000 +0200
@@ -1,4 +1,4 @@
-from distutils.core import setup
+from setuptools import setup
from gnupg import __version__ as version
@@ -24,16 +24,10 @@
"Programming Language :: Python",
"Programming Language :: Python :: 2",
"Programming Language :: Python :: 3",
- "Programming Language :: Python :: 2.4",
- "Programming Language :: Python :: 2.5",
- "Programming Language :: Python :: 2.6",
"Programming Language :: Python :: 2.7",
- "Programming Language :: Python :: 3.2",
- "Programming Language :: Python :: 3.3",
- "Programming Language :: Python :: 3.4",
- "Programming Language :: Python :: 3.5",
"Programming Language :: Python :: 3.6",
"Programming Language :: Python :: 3.7",
+ "Programming Language :: Python :: 3.8",
"Operating System :: OS Independent",
"Topic :: Software Development :: Libraries :: Python Modules"
]
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/python-gnupg-0.4.5/test_gnupg.py
new/python-gnupg-0.4.6/test_gnupg.py
--- old/python-gnupg-0.4.5/test_gnupg.py 2019-08-12 18:47:20.000000000
+0200
+++ new/python-gnupg-0.4.6/test_gnupg.py 2020-04-17 10:36:09.000000000
+0200
@@ -2,9 +2,11 @@
"""
A test harness for gnupg.py.
-Copyright (C) 2008-2018 Vinay Sajip. All rights reserved.
+Copyright (C) 2008-2020 Vinay Sajip. All rights reserved.
"""
import doctest
+import io
+import json
import logging
import os.path
import os
@@ -28,7 +30,7 @@
import gnupg
__author__ = "Vinay Sajip"
-__date__ = "$12-Aug-2019 15:58:32$"
+__date__ = "$17-Apr-2020 09:36:09$"
ALL_TESTS = True
@@ -136,6 +138,40 @@
-----END PGP PUBLIC KEY BLOCK-----
"""
+SECRET_KEY = """
+-----BEGIN PGP PRIVATE KEY BLOCK-----
+
+lQPGBFztd1UBCACiHhlEJIGfXNEiUX4GwamgdLOkJ3mbn5OyV4M/Ie3YvvHxveq/
+TFYbuV63iuDVhNXpDUNmGsTq4vFaMsseLl7eESw8UTa3XklHHjh56kw0AVkJA75A
+Xq/VshFobLNxYZdtlOVkKe1a3uJVKs+BqFjhavEjQyhkpWvBY51OzCSc2AN/aQZA
+F3AltZ8luIHZPs8zVbgH90WIpze+vzAd9FyXD0wV6gylGSifHj8zIhac80evQgD9
+50De7EPnSdgZSNwnlrhQtAIB5UnTETxXk34/W0Rq+BKn6SuchtaP7hXIHC0+B0C7
+zBzPYKMQ7vXc/hceNwSGtgovhaQPCcv1byFBABEBAAH+BwMCUNdAVY/RMdJg1q5n
+FQOyVZl2tvd3krExjGYvhabwijbPz+TrVkPhKqdkp4Hbf3oXV/bcbQhG2dld4Ooc
++xtEpTqYw08bNDuk4NEAvggasUkgssHZccDmHySGfA9U8C7B0Hj8xT4SifnuVNL+
+xp9iv1BS03s+UIEVZ2rGjDQy7/G/U6/ZpLqFg+C113VQs6yz0VMsnnAQOMgN0+gQ
+aZb6VNPR7nZ5+/hRlx0DgXu++lei9HTmHRz+ZvbbYjeU9nj10eANhO0lEvlgtyXa
+v4Y5ERwk86gbkSRGtN88qVK/+GXK60Q33EoGMlwPZrfFGx+N5QuPEnCjT1vvz7E3
+HhCpe4u5Idusgui+tDkxq8BEz6iTGMO1hcb75MDdIQBhJzeJ7OIxyBfqLReF4+Ut
+eNwy0wpN3xuEeYvP4ZIe7hj74WWIuKq2+lesPm4eWRPoaQ5MZXmEwbjr29e++V7D
+EkHgCYio6TVwrHA0LRSNfm8VVBV2cdsqFOLLutudHoC8BnjetEetmYaA99u0Pevz
+NscYwfaWLNW/d5FGyPUb+GQFYzmQWUfUzpg9hu7U79uA0kOwC+4nK6LEalILtoHn
+YO3PvvcCEnpWBlDhCR3n0zkNQCulvQKS/ww5q/MDNqvibKiMJHJ1xP89tEU3lnHl
+qgwHVmleqUR+yzdg5lo96Yey5yaDdhK5ZR1TFC4qK4Igcn2+WG109659bJUGpEre
+Vktu530JutX38ZoyKdHO0uPs/ft/hgBhNd6MKmh7eejo84Wn6/lxkfMydkfKm5QY
+dMHF3Ew+l7aACAs3l95V0YDNzA0FyOFkb/tqxyx8dP+O2NdZQZSvG+yxDav05bCq
+kwz+7H7sJnUj1JJtUgPTL9yVH+LyUhL8AU13UKVjBFJ4VL5+KDD9KwPkk6aN7zDW
+Qv0g8Cc7A8H0tB5BdXRvZ2VuZXJhdGVkIEtleSA8dXNlcjFAdGVzdD6JATgEEwEI
+ACIFAlztd1UCGy8GCwkIBwMCBhUIAgkKCwQWAgMBAh4BAheAAAoJEGP32fXSIJgg
+IXgH/3o1rUzbjjz1sMoBwRv4qLmgeqlB2YJSVzLWOn4AcrHbxup5O9nJkqG+YFwH
+OFmytuiPDKmA4ZXww8f+2rHXdDuwI5SWnfhuPpV863BulIhtjwiwqD9eIzQ9LX79
+K7hXRJ4I0AkYEbDHOWlLHZCrjul/ZaS10QRVR21EYICha2I8tvxsRMPp0I93XnuB
+T+z7ykRxRjpMv6MfhWVcw5B0s7lPedLhcx657HfY49t36/CIZ9/zMKsduX7cTOAh
+tO8f06R3yfjxLRD8y89frVP3+tGMvt2yGOd5TT0zht5yYcG6QkiHlfdgXqeE8nsU
+2392Xn/RETq6xCj3kG6K3wbWqh0=
+=2A5s
+-----END PGP PRIVATE KEY BLOCK-----
+"""
def is_list_with_len(o, n):
return isinstance(o, list) and len(o) == n
@@ -157,19 +193,30 @@
# ignoring things like spurious blank lines
return get_key_data(k1) != get_key_data(k2)
-AGENT_CONFIG = b'''allow-loopback-pinentry
+AGENT_CONFIG = '''allow-loopback-pinentry
log-file socket:///tmp/S.my-gnupg-log
verbose
debug ipc
'''
+ENABLE_TOFU = 'ENABLE_TOFU' in os.environ
+
+if ENABLE_TOFU:
+ GPG_CONFIG = 'trust-model tofu+pgp\ntofu-default-policy unknown\n'
+
+
def prepare_homedir(hd):
if not os.path.isdir(hd):
os.makedirs(hd)
os.chmod(hd, 0x1C0)
fn = os.path.join(hd, 'gpg-agent.conf')
- with open(fn, 'wb') as f:
+ with open(fn, 'w') as f:
f.write(AGENT_CONFIG)
+ if ENABLE_TOFU:
+ fn = os.path.join(hd, 'gpg.conf')
+ with open(fn, 'w') as f:
+ f.write(GPG_CONFIG)
+
class GPGTestCase(unittest.TestCase):
def setUp(self):
@@ -305,8 +352,8 @@
self.assertEqual(uid, 'Test Name (Funny chars: '
'\r\n\x0c\x0b\x00\x08) <[email protected]>')
- def test_key_generation_with_empty_value(self):
- "Test that key generation handles empty values"
+ def test_key_generation_input(self):
+ "Test that key generation input handles empty values, curves etc."
params = {
'key_type': ' ',
'key_length': 2048,
@@ -316,6 +363,18 @@
params['key_type'] = 'DSA'
cmd = self.gpg.gen_key_input(**params)
self.assertTrue('Key-Type: DSA\n' in cmd)
+ params = {
+ 'key_type': 'ECDSA',
+ 'key_curve': 'nistp384',
+ 'subkey_type': 'ECDH',
+ 'subkey_curve': 'nistp384',
+ 'name_comment': 'NIST P-384',
+ }
+ cmd = self.gpg.gen_key_input(**params)
+ for s in ('Key-Type: ECDSA', 'Key-Curve: nistp384', 'Subkey-Type:
ECDH',
+ 'Subkey-Curve: nistp384', 'Name-Comment: NIST P-384'):
+ self.assertTrue('%s\n' %s in cmd)
+ self.assertFalse('Key-Length: ' in cmd)
def test_list_keys_after_generation(self):
"Test that after key generation, the generated key is available"
@@ -448,6 +507,11 @@
for key in keys:
self.assertEqual(key['ownertrust'], expected)
self.assertRaises(ValueError, gpg.trust_keys, fingerprints,
'TRUST_FOOBAR')
+ self.assertRaises(ValueError, gpg.trust_keys, 'NO_SUCH_FINGERPRINT',
'TRUST_NEVER')
+ # gpg should raise an error for the following - but it doesn't!
+ # self.assertRaises(ValueError, gpg.trust_keys,
+ # 'BADF00DBADF00DBADF00DBADF00DBADF00DBADF0',
+ # 'TRUST_NEVER')
def test_list_signatures(self):
logger.debug("test_list_signatures begins")
@@ -599,6 +663,19 @@
binary = gpg.export_keys(key.fingerprint, True, armor=False,
passphrase=passphrase)
self.assertFalse(isinstance(binary, gnupg.text_type))
+ # import a secret key, and confirm that it's found in the list of
+ # secret keys.
+ result = gpg.import_keys(SECRET_KEY)
+ self.assertEqual(result.summary(), '1 imported')
+ private_keys = gpg.list_keys(secret=True)
+ self.assertTrue(is_list_with_len(private_keys, 2))
+ found = False
+ for pk in private_keys:
+ if pk['keyid'].endswith('D2209820'):
+ found = True
+ break
+ self.assertTrue(found)
+ self.assertEqual(pk['uids'][0], 'Autogenerated Key <user1@test>')
logger.debug("test_import_and_export ends")
def test_import_only(self):
@@ -846,8 +923,8 @@
encfno, encfname = tempfile.mkstemp()
os.close(encfno)
cases = (
- ('/dev/null/foo', 'not a directory'),
- ('/etc/foo', 'permission denied'),
+ ('/dev/null/foo', 'encrypt: not a directory'),
+ ('/etc/foo', 'encrypt: permission denied'),
)
key = self.generate_key("Barbara", "Brown", "beta.com")
barbara = key.fingerprint
@@ -861,6 +938,31 @@
if edata.status:
self.assertEqual(edata.status, message)
+ # now try with custom error map, if available
+ if os.path.exists('messages.json'):
+ with open('messages.json') as f:
+ mdata = json.load(f)
+ messages = {}
+ for k, v in mdata.items():
+ messages[int(k, 16)] = v
+
+ self.gpg.error_map = messages
+
+ cases = (
+ ('/dev/null/foo', 'encrypt: Not a directory'),
+ ('/etc/foo', 'encrypt: Permission denied'),
+ )
+
+ for badout, message in cases:
+ stream = gnupg._make_binary_stream(data, self.gpg.encoding)
+ edata = self.gpg.encrypt_file(stream,
+ barbara, armor=False,
output=badout)
+ # on GnuPG 1.4, you sometimes don't get any FAILURE messages,
in
+ # which case status will not be set
+ if edata.status:
+ self.assertEqual(edata.status, message)
+
+
def test_filenames_with_spaces(self): # See Issue #16
"Test that filenames with spaces are correctly handled"
logger.debug("test_filename_with_spaces begins")
@@ -1011,6 +1113,10 @@
self.assertFalse(result)
logger.debug("test_doctest_import_keys ends")
+ def test_recv_keys_no_server(self):
+ result = self.gpg.recv_keys('foo.bar.baz', '92905378')
+ self.assertEqual(result.summary(), '0 imported')
+
TEST_GROUPS = {
'sign' : set(['test_signature_verification',
@@ -1023,14 +1129,14 @@
'test_list_signatures',
'test_key_generation_with_invalid_key_type',
'test_key_generation_with_escapes',
- 'test_key_generation_with_empty_value',
+ 'test_key_generation_input',
'test_key_generation_with_colons',
'test_search_keys', 'test_scan_keys', 'test_key_trust']),
'import' : set(['test_import_only', 'test_doctest_import_keys']),
'basic' : set(['test_environment', 'test_list_keys_initial',
'test_nogpg', 'test_make_args',
'test_quote_with_shell']),
- 'test': set(['test_encryption_and_decryption']),
+ 'test': set(['test_invalid_outputs']),
}
def suite(args=None):