Merge branch 'fix/82-passphrase-empty-str' into develop

fix/102-py3k-decrypt-bytes-literal
Isis Lovecruft 2015-03-18 19:40:23 +00:00
commit 94f81c3226
No known key found for this signature in database
GPG Key ID: 18C16EC5F9F1D673
3 changed files with 131 additions and 0 deletions

View File

@ -46,6 +46,8 @@ except ImportError:
from . import _parsers
from . import _util
from ._util import b
from ._util import s
from ._parsers import _check_preferences
from ._parsers import _sanitise_list
@ -804,6 +806,19 @@ class GPGBase(object):
## We could use _handle_io here except for the fact that if the
## passphrase is bad, gpg bails and you can't write the message.
result = self._result_map['sign'](self)
## If the passphrase is an empty string, the message up to and
## including its first newline will be cut off before making it to the
## GnuPG process. Therefore, if the passphrase='' or passphrase=b'',
## we set passphrase=None. See Issue #82:
## https://github.com/isislovecruft/python-gnupg/issues/82
if _util._is_string(passphrase):
passphrase = passphrase if len(passphrase) > 0 else None
elif _util._is_bytes(passphrase):
passphrase = s(passphrase) if len(passphrase) > 0 else None
else:
passphrase = None
proc = self._open_subprocess(args, passphrase is not None)
try:
if passphrase:

View File

@ -165,6 +165,33 @@ def find_encodings(enc=None, system=False):
return coder
if _py3k:
def b(x):
"""See http://python3porting.com/problems.html#nicer-solutions"""
return x
def s(x):
if isinstance(x, str):
return x
elif isinstance(x, (bytes, bytearray)):
return x.decode(find_encodings().name)
else:
raise NotImplemented
else:
def b(x):
"""See http://python3porting.com/problems.html#nicer-solutions"""
return find_encodings().encode(x)[0]
def s(x):
if isinstance(x, basestring):
return x
elif isinstance(x, (bytes, bytearray)):
return x.decode(find_encodings().name)
else:
raise NotImplemented
def author_info(name, contact=None, public_key=None):
"""Easy object-oriented representation of contributor info.
@ -440,6 +467,31 @@ def _is_stream(input):
"""
return isinstance(input, tuple(_STREAMLIKE_TYPES))
def _is_string(thing):
"""Check that **thing** is a string. The definition of the latter depends
upon the Python version.
:param thing: The thing to check if it's a string.
:rtype: bool
:returns: ``True`` if **thing** is string (or unicode in Python2).
"""
if (_py3k and isinstance(thing, str)):
return True
if (not _py3k and isinstance(thing, basestring)):
return True
return False
def _is_bytes(thing):
"""Check that **thing** is bytes.
:param thing: The thing to check if it's bytes.
:rtype: bool
:returns: ``True`` if **thing** is bytes or a bytearray.
"""
if isinstance(thing, (bytes, bytearray)):
return True
return False
def _is_list_or_tuple(instance):
"""Check that ``instance`` is a list or tuple.

View File

@ -626,6 +626,66 @@ class GPGTestCase(unittest.TestCase):
passphrase='wrong horse battery staple')
self.assertFalse(sig, "Bad passphrase should fail")
def test_signature_string_passphrase_empty_string(self):
"""Test that a signing attempt with passphrase='' creates a valid
signature.
See Issue #82: https://github.com/isislovecruft/python-gnupg/issues/82
"""
with open(os.path.join(_files, 'test_key_1.sec')) as fh1:
res1 = self.gpg.import_keys(fh1.read())
key1 = res1.fingerprints[0]
message = 'abc\ndef\n'
sig = self.gpg.sign(message, default_key=key1, passphrase='')
self.assertTrue(sig)
self.assertTrue(message in str(sig))
def test_signature_string_passphrase_empty_bytes_literal(self):
"""Test that a signing attempt with passphrase=b'' creates a valid
signature.
See Issue #82: https://github.com/isislovecruft/python-gnupg/issues/82
"""
with open(os.path.join(_files, 'test_key_1.sec')) as fh1:
res1 = self.gpg.import_keys(fh1.read())
key1 = res1.fingerprints[0]
message = 'abc\ndef\n'
sig = self.gpg.sign(message, default_key=key1, passphrase=b'')
self.assertTrue(sig)
print("%r" % str(sig))
self.assertTrue(message in str(sig))
def test_signature_string_passphrase_bytes_literal(self):
"""Test that a signing attempt with passphrase=b'overalls' creates a
valid signature.
"""
with open(os.path.join(_files, 'kat.sec')) as fh1:
res1 = self.gpg.import_keys(fh1.read())
key1 = res1.fingerprints[0]
message = 'abc\ndef\n'
sig = self.gpg.sign(message, default_key=key1, passphrase=b'overalls')
self.assertTrue(sig)
print("%r" % str(sig))
self.assertTrue(message in str(sig))
def test_signature_string_passphrase_None(self):
"""Test that a signing attempt with passphrase=None fails creates a
valid signature.
See Issue #82: https://github.com/isislovecruft/python-gnupg/issues/82
"""
with open(os.path.join(_files, 'test_key_1.sec')) as fh1:
res1 = self.gpg.import_keys(fh1.read())
key1 = res1.fingerprints[0]
message = 'abc\ndef\n'
sig = self.gpg.sign(message, default_key=key1, passphrase=None)
self.assertTrue(sig)
self.assertTrue(message in str(sig))
def test_signature_file(self):
"""Test that signing a message file works."""
key = self.generate_key("Leonard Adleman", "rsa.com")
@ -1339,6 +1399,10 @@ suites = { 'parsers': set(['test_parsers_fix_unsafe',
'test_signature_verification_detached',
'test_signature_verification_detached_binary',
'test_signature_file',
'test_signature_string_passphrase_empty_string',
'test_signature_string_passphrase_empty_bytes_literal',
'test_signature_string_passphrase_bytes_literal',
'test_signature_string_passphrase_None',
'test_signature_string_bad_passphrase',
'test_signature_string_verification',
'test_signature_string_algorithm_encoding']),