Merge branch 'master' into master

This commit is contained in:
James Morris
2020-09-24 17:38:54 -04:00
committed by GitHub
28 changed files with 300 additions and 165 deletions

View File

@@ -15,4 +15,4 @@ __all__ = ['__author__',
__author__ = "Michael Greene"
__copyright__ = "Copyright (c) 2014-2019 Security Innovation, Inc"
__license__ = "BSD"
__version__ = str(LooseVersion("0.5.2"))
__version__ = str(LooseVersion("0.5.3"))

View File

@@ -53,6 +53,7 @@ class Backend(Enum):
class EllipticCurveOID(Enum):
"""OIDs for supported elliptic curves."""
# these are specified as:
# id = (oid, curve)
Invalid = ('', )
@@ -242,6 +243,7 @@ class SymmetricKeyAlgorithm(IntEnum):
class PubKeyAlgorithm(IntEnum):
"""Supported public key algorithms."""
Invalid = 0x00
#: Signifies that a key is an RSA key.
RSAEncryptOrSign = 0x01
@@ -283,6 +285,7 @@ class PubKeyAlgorithm(IntEnum):
class CompressionAlgorithm(IntEnum):
"""Supported compression algorithms."""
#: No compression
Uncompressed = 0x00
#: ZIP DEFLATE
@@ -327,6 +330,7 @@ class CompressionAlgorithm(IntEnum):
class HashAlgorithm(IntEnum):
"""Supported hash algorithms."""
Invalid = 0x00
MD5 = 0x01
SHA1 = 0x02
@@ -362,6 +366,7 @@ class HashAlgorithm(IntEnum):
class RevocationReason(IntEnum):
"""Reasons explaining why a key or certificate was revoked."""
#: No reason was specified. This is the default reason.
NotSpecified = 0x00
#: The key was superseded by a new key. Only meaningful when revoking a key.
@@ -387,21 +392,83 @@ class ImageEncoding(IntEnum):
class SignatureType(IntEnum):
"""Types of signatures that can be found in a Signature packet."""
#: The signer either owns this document, created it, or certifies that it
#: has not been modified.
BinaryDocument = 0x00
#: The signer either owns this document, created it, or certifies that it
#: has not been modified. The signature is calculated over the text
#: data with its line endings converted to ``<CR><LF>``.
CanonicalDocument = 0x01
#: This signature is a signature of only its own subpacket contents.
#: It is calculated identically to a signature over a zero-length
#: ``BinaryDocument``.
Standalone = 0x02
#: The issuer of this certification does not make any particular
#: claim as to how well the certifier has checked that the owner
#: of the key is in fact the person described by the User ID.
Generic_Cert = 0x10
#: The issuer of this certification has not done any verification of
#: the claim that the owner of this key is the User ID specified.
Persona_Cert = 0x11
#: The issuer of this certification has done some casual
#: verification of the claim of identity.
Casual_Cert = 0x12
#: The issuer of this certification has done substantial
#: verification of the claim of identity.
Positive_Cert = 0x13
#: This signature is issued by the primary key over itself and its user ID (or user attribute).
#: See `draft-ietf-openpgp-rfc4880bis-08 <https://tools.ietf.org/html/draft-ietf-openpgp-rfc4880bis-08#section-5.2.1>`_
Attestation = 0x16
#: This signature is a statement by the top-level signing key that
#: indicates that it owns the subkey. This signature is calculated
#: directly on the primary key and subkey, and not on any User ID or
#: other packets.
Subkey_Binding = 0x18
#: This signature is a statement by a signing subkey, indicating
#: that it is owned by the primary key and subkey. This signature
#: is calculated the same way as a ``Subkey_Binding`` signature.
PrimaryKey_Binding = 0x19
#: A signature calculated directly on a key. It binds the
#: information in the Signature subpackets to the key, and is
#: appropriate to be used for subpackets that provide information
#: about the key, such as the Revocation Key subpacket. It is also
#: appropriate for statements that non-self certifiers want to make
#: about the key itself, rather than the binding between a key and a
#: name.
DirectlyOnKey = 0x1F
#: A signature calculated directly on the key being revoked.
#: Only revocation signatures by the key being revoked, or by an
#: authorized revocation key, should be considered valid revocation signatures.
KeyRevocation = 0x20
#: A signature calculated directly on the subkey being revoked.
#: Only revocation signatures by the top-level signature key that is bound to this subkey,
#: or by an authorized revocation key, should be considered valid revocation signatures.
SubkeyRevocation = 0x28
#: This signature revokes an earlier User ID certification signature or direct-key signature.
#: It should be issued by the same key that issued the revoked signature or an authorized revocation key.
#: The signature is computed over the same data as the certificate that it revokes.
CertRevocation = 0x30
#: This signature is only meaningful for the timestamp contained in it.
Timestamp = 0x40
#: This signature is a signature over some other OpenPGP Signature
#: packet(s). It is analogous to a notary seal on the signed data.
ThirdParty_Confirmation = 0x50
@@ -433,6 +500,7 @@ class TrustLevel(IntEnum):
class KeyFlags(FlagEnum):
"""Flags that determine a key's capabilities."""
#: Signifies that a key may be used to certify keys and user ids. Primary keys always have this, even if it is not specified.
Certify = 0x01
#: Signifies that a key may be used to sign messages and documents.

View File

@@ -651,9 +651,11 @@ class PGPUID(ParentRef):
@property
def is_primary(self):
"""
If the most recent, valid self-signature specifies this as being primary, this will be True. Otherwise, Faqlse.
If the most recent, valid self-signature specifies this as being primary, this will be True. Otherwise, False.
"""
return bool(next(iter(self.selfsig._signature.subpackets['h_PrimaryUserID']), False))
if self.selfsig is not None:
return bool(next(iter(self.selfsig._signature.subpackets['h_PrimaryUserID']), False))
return False
@property
def is_uid(self):
@@ -791,7 +793,13 @@ class PGPUID(ParentRef):
def __lt__(self, other): # pragma: no cover
if self.is_uid == other.is_uid:
if self.is_primary == other.is_primary:
return self.selfsig > other.selfsig
mysig = self.selfsig
othersig = other.selfsig
if mysig is None:
return not (othersig is None)
if othersig is None:
return False
return mysig > othersig
if self.is_primary:
return True
@@ -844,7 +852,7 @@ class PGPUID(ParentRef):
class PGPMessage(Armorable, PGPObject):
@staticmethod
def dash_unescape(text):
return re.subn(r'^- -', '-', text, flags=re.MULTILINE)[0]
return re.subn(r'^- ', '', text, flags=re.MULTILINE)[0]
@staticmethod
def dash_escape(text):
@@ -936,10 +944,10 @@ class PGPMessage(Armorable, PGPObject):
"""
PGPMessage objects represent OpenPGP message compositions.
PGPMessage implements the `__str__` method, the output of which will be the message composition in
PGPMessage implements the ``__str__`` method, the output of which will be the message composition in
OpenPGP-compliant ASCII-armored format.
PGPMessage implements the `__bytes__` method, the output of which will be the message composition in
PGPMessage implements the ``__bytes__`` method, the output of which will be the message composition in
OpenPGP-compliant binary format.
Any signatures within the PGPMessage that are marked as being non-exportable will not be included in the output
@@ -1168,11 +1176,14 @@ class PGPMessage(Armorable, PGPObject):
def encrypt(self, passphrase, sessionkey=None, **prefs):
"""
encrypt(passphrase, [sessionkey=None,] **prefs)
Encrypt the contents of this message using a passphrase.
:param passphrase: The passphrase to use for encrypting this message.
:type passphrase: ``str``, ``unicode``, ``bytes``
:optional param sessionkey: Provide a session key to use when encrypting something. Default is ``None``.
:param sessionkey: Provide a session key to use when encrypting something. Default is ``None``.
If ``None``, a session key of the appropriate length will be generated randomly.
.. warning::
@@ -1438,8 +1449,10 @@ class PGPKey(Armorable, ParentRef, PGPObject):
@property
def key_size(self):
"""*new in 0.4.1*
"""
The size pertaining to this key. ``int`` for non-EC key algorithms; :py:obj:`constants.EllipticCurveOID` for EC keys.
.. versionadded:: 0.4.1
"""
if self.key_algorithm in {PubKeyAlgorithm.ECDSA, PubKeyAlgorithm.ECDH, PubKeyAlgorithm.EdDSA}:
return self._key.keymaterial.oid
@@ -1565,13 +1578,13 @@ class PGPKey(Armorable, ParentRef, PGPObject):
Generate a new PGP key
:param key_algorithm: Key algorithm to use.
:type key_algorithm: A :py:obj:`~constants.PubKeyAlgorithm`
:type key_algorithm: :py:obj:`~constants.PubKeyAlgorithm`
:param key_size: Key size in bits, unless `key_algorithm` is :py:obj:`~constants.PubKeyAlgorithm.ECDSA` or
:py:obj:`~constants.PubKeyAlgorithm.ECDH`, in which case it should be the Curve OID to use.
:type key_size: ``int`` or :py:obj:`~constants.EllipticCurveOID`
:param created: When was the key created? (None or unset means now)
:type created: :py:obj:`~datetime.datetime` or None
:param created: When was the key created? (``None`` or unset means now)
:type created: :py:obj:`~datetime.datetime` or ``None``
:return: A newly generated :py:obj:`PGPKey`
"""
# new private key shell first
@@ -1761,7 +1774,8 @@ class PGPKey(Armorable, ParentRef, PGPObject):
Emits a :py:obj:`~warnings.UserWarning` if the key is public or not passphrase protected.
:param str passphrase: The passphrase to be used to unlock this key.
:param passphrase: The passphrase to be used to unlock this key.
:type passphrase: ``str``
:raises: :py:exc:`~pgpy.errors.PGPDecryptionError` if the passphrase is incorrect
"""
if self.is_public:
@@ -2027,6 +2041,8 @@ class PGPKey(Armorable, ParentRef, PGPObject):
@KeyAction(KeyFlags.Certify, is_unlocked=True, is_public=False)
def certify(self, subject, level=SignatureType.Generic_Cert, **prefs):
"""
certify(subject, level=SignatureType.Generic_Cert, **prefs)
Sign a key or a user id within a key.
:param subject: The user id or key to be certified.
@@ -2385,12 +2401,13 @@ class PGPKey(Armorable, ParentRef, PGPObject):
@KeyAction(KeyFlags.EncryptCommunications, KeyFlags.EncryptStorage, is_public=True)
def encrypt(self, message, sessionkey=None, **prefs):
"""
"""encrypt(message[, sessionkey=None], **prefs)
Encrypt a PGPMessage using this key.
:param message: The message to encrypt.
:type message: :py:obj:`PGPMessage`
:optional param sessionkey: Provide a session key to use when encrypting something. Default is ``None``.
:param sessionkey: Provide a session key to use when encrypting something. Default is ``None``.
If ``None``, a session key of the appropriate length will be generated randomly.
.. warning::
@@ -2676,7 +2693,7 @@ class PGPKeyring(collections_abc.Container, collections_abc.Iterable, collection
r"""
Load all keys provided into this keyring object.
:param \*args: Each arg in ``args`` can be any of the formats supported by :py:meth:`PGPKey.from_path` and
:param \*args: Each arg in ``args`` can be any of the formats supported by :py:meth:`PGPKey.from_file` and
:py:meth:`PGPKey.from_blob` or a :py:class:`PGPKey` instance, or a ``list`` or ``tuple`` of these.
:type \*args: ``list``, ``tuple``, ``str``, ``unicode``, ``bytes``, ``bytearray``
:returns: a ``set`` containing the unique fingerprints of all of the keys that were loaded during this operation.
@@ -2727,10 +2744,12 @@ class PGPKeyring(collections_abc.Container, collections_abc.Iterable, collection
"""
List loaded fingerprints with some optional filtering.
:param str keyhalf: Can be 'any', 'public', or 'private'. If 'public', or 'private', the fingerprints of keys of the
:param keyhalf: Can be 'any', 'public', or 'private'. If 'public', or 'private', the fingerprints of keys of the
the other type will not be included in the results.
:param str keytype: Can be 'any', 'primary', or 'sub'. If 'primary' or 'sub', the fingerprints of keys of the
:type keyhalf: ``str``
:param keytype: Can be 'any', 'primary', or 'sub'. If 'primary' or 'sub', the fingerprints of keys of the
the other type will not be included in the results.
:type keytype: ``str``
:returns: a ``set`` of fingerprints of keys matching the filters specified.
"""
return {pk.fingerprint for pk in self._keys.values()
@@ -2743,13 +2762,13 @@ class PGPKeyring(collections_abc.Container, collections_abc.Iterable, collection
"""
Unload a loaded key and its subkeys.
:param key: The key to unload.
:type key: :py:obj:`PGPKey`
The easiest way to do this is to select a key using :py:meth:`PGPKeyring.key` first::
with keyring.key("DSA von TestKey") as key:
keyring.unload(key)
:param key: The key to unload.
:type key: :py:obj:`PGPKey`
"""
assert isinstance(key, PGPKey)
pkid = id(key)

View File

@@ -616,7 +616,7 @@ class SignatureVerification(object):
def __init__(self):
"""
Returned by :py:meth:`PGPKey.verify`
Returned by :py:meth:`.PGPKey.verify`
Can be compared directly as a boolean to determine whether or not the specified signature verified.
"""