Merge branch 'master' into master
This commit is contained in:
@@ -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"))
|
||||
|
||||
@@ -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.
|
||||
|
||||
59
pgpy/pgp.py
59
pgpy/pgp.py
@@ -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)
|
||||
|
||||
@@ -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.
|
||||
"""
|
||||
|
||||
Reference in New Issue
Block a user