Workaround possible upstream GnuPG bug sign fail when passphrase=''.
If passed `--passphrase-fd 0` and piped the passphrase `''` (an empty string), GnuPG will truncate the message being signed. The truncation appears to only affect messages which contain newlines; for those messages, the first line (up unto and including the newline character) will be truncated and thus missing from the output signed message or signature, causing verification for signatures on the original non-truncated message to fail. * FIXES #82: https://github.com/isislovecruft/python-gnupg/issues/82fix/82-passphrase-empty-str
parent
9be01ec6df
commit
16107bc8a8
|
@ -46,6 +46,8 @@ except ImportError:
|
||||||
|
|
||||||
from . import _parsers
|
from . import _parsers
|
||||||
from . import _util
|
from . import _util
|
||||||
|
from ._util import b
|
||||||
|
from ._util import s
|
||||||
|
|
||||||
from ._parsers import _check_preferences
|
from ._parsers import _check_preferences
|
||||||
from ._parsers import _sanitise_list
|
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
|
## 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.
|
## passphrase is bad, gpg bails and you can't write the message.
|
||||||
result = self._result_map['sign'](self)
|
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)
|
proc = self._open_subprocess(args, passphrase is not None)
|
||||||
try:
|
try:
|
||||||
if passphrase:
|
if passphrase:
|
||||||
|
|
|
@ -165,6 +165,33 @@ def find_encodings(enc=None, system=False):
|
||||||
|
|
||||||
return coder
|
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):
|
def author_info(name, contact=None, public_key=None):
|
||||||
"""Easy object-oriented representation of contributor info.
|
"""Easy object-oriented representation of contributor info.
|
||||||
|
|
||||||
|
@ -440,6 +467,31 @@ def _is_stream(input):
|
||||||
"""
|
"""
|
||||||
return isinstance(input, tuple(_STREAMLIKE_TYPES))
|
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):
|
def _is_list_or_tuple(instance):
|
||||||
"""Check that ``instance`` is a list or tuple.
|
"""Check that ``instance`` is a list or tuple.
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue