Esempio n. 1
0
    def _read_message(self, message):
        if not isinstance(message, Message):
            raise TypeError("expected a protonmail.models.Message instance")

        # If the message hasn't been read yet, do that now
        if not message.Body:
            resp = yield self.api.messages(message.ID,
                                           blocking=False,
                                           response=responses.MessageResponse)
            if resp.Code != 1000:
                raise ValueError("Unexpected response: {}".format(
                    resp.to_json()))
            message = resp.Message

        # Read and decrypt if needed
        msg = PGPMessage.from_blob(message.Body)
        if msg.is_signed:
            email = message.SenderAddress
            if email not in self.PublicKeys:
                yield self._get_public_key(email)
            pk = self.PublicKeys.get(email)
            if not pk:
                raise SecurityError("Failed to verify signed message!")
            pk[0].verify(msg)  # TODO: Support mutiple keys

        # Decrypt
        with self.PrivateKey.unlock(self.MailboxPassword) as key:
            message.decrypt(key)
        return_value(message)
Esempio n. 2
0
def test_spurious_dash_escapes():
    from pgpy import PGPKey, PGPMessage

    message_data = r'''-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1,SHA256

- This is stored, literally\!

-----BEGIN PGP SIGNATURE-----
Version: GnuPG/MacGPG2 v2.0.20 (Darwin)

iJwEAQECAAYFAlQaCpEACgkQBM3VPIdAqKYrhwQAyQhwiqrR6oZ5fTBm4JyCOEND
72Kxbaz1i9Qh0jv7DmgRjb4udh95UQ8U0qVnmnhA8E2deKeDcWTS4fzUkU6J9OdH
/GPHpL9QEtOJ7xifzJsnKaNJVynmNMtYOqHQ9gCmXx7jM2ngxbTKBT8YZlSLMUdO
uoUFKrJGv0LWlSWHkeOJARwEAQECAAYFAlQaCpEACgkQKoNNjlkY6IYrhwf/ZnMN
yKIVxGl+5/9oovvgz2MtGt9B09xRg4BqD+lUDshzQUvQIjBXZ7ZEGSWqerRymZDg
ZzHpb1lv9oAOVU8f1qsMQJJkiz7Q+xu5FfgAp0WzMHJNy4QOmB4Kw/7UbTwdUXzw
EzKwbJ8Eg97vJgYdfqUZLu949dwJvyYZzGDdkbrnsaZ8H29XkKXNMlMinDQjvFBR
djgkILl3ZIdC3p+KechV3uYsqwje2qNEo69KukihPhzCe9o6/Yub5gdC+DSQDGl4
uPjk0zXjds4G5J5Jd5g4o7vhDWs8InxX4AcLfD6lH1XQ1VCZBpucun5CVsU3dUAv
yvO7C7FubDu1GUxdbYheBAERCAAGBQJUGgqRAAoJEKXc3JZkUxQOZ+IA/3KI8Mnl
k3jfpRQcvtSYFlU9WZk9SqZX6xirnV7Hloq6AP9ZlivPrJdWmjRyyShkMNgP/c63
cjMX82ahGPUVlyMP4A==
=bcSu
-----END PGP SIGNATURE-----
'''

    key = PGPKey.from_file('tests/testdata/keys/rsa.1.pub.asc')[0]
    message = PGPMessage.from_blob(message_data)
    assert key.verify(message)
Esempio n. 3
0
    def __init__(self, config, secrets):
        try:
            dataKeyBytes = config.get("key", None)
        except AttributeError as e:
            raise InvalidConfig(original=e)

        if not dataKeyBytes or dataKeyBytes == "":
            msg = ("crypto.key is not a string, "
                   "Remove the crypto property if encryption is not needed")
            raise InvalidConfig(message=msg)

        privateKey = secrets.get("privateKey", None)
        if not privateKey or privateKey == "":
            msg = ("No gpg private key provided for decryption. "
                   "Remove the crypto property if encryption is not needed")
            raise InvalidConfig(message=msg)

        gpgKey = PGPKey()
        gpgKey.parse(privateKey)

        password = secrets.get("privateKeyPassword", None)
        if password:
            try:
                gpgKey.unlock(password)
            except PGPDecryptionError as err:
                raise BadGPGKeyPasswordError(gpgKey.userids[0])

        with warnings.catch_warnings():
            # prevents warning of type `UserWarning: Message was encrypted with this key's subkey: ...`
            warnings.simplefilter("ignore", category=UserWarning)
            dataKey = gpgKey.decrypt(
                PGPMessage.from_blob(dataKeyBytes)).message

        DataKeyService.__init__(self, dataKey)
Esempio n. 4
0
def decrypt_session_key(blob, key=None, password=None):
    """ Decrypt the session key from the given PGPMessage blob
    
    Parameters
    ----------
    blob: String or Bytes
        PGP Message data
    key: pgpy.PGPKey
        The private PGPKey for decryption. It MUST be unlocked.
    password: String or Bytes
        The password for decryption
    
    Returns
    -------
    result: Tuple[pgpy.constants.SymmetricKeyAlgorithm, Bytes]
        The algo and session key
    
    """
    message = PGPMessage.from_blob(blob)
    for sk in message._sessionkeys:
        k = key.subkeys.get(sk.encrypter)
        if k is not None:
            cipher, session_key = sk.decrypt_sk(k._key)
            return cipher, bytes(session_key)
    raise KeyError("Key not found")
Esempio n. 5
0
def check_mailbox_password(key, password, access_token):
    """ Make sure the password is valid by decrypting the access token.
    
    Parameters
    ----------
    key: Bytes
        PGP Private key
    password: String
    access_token: String
        Access token as an encrypted PGP message 
    Returns
    -------
    token: String

    """
    if not key:
        raise ValueError("Missing private key")
    if not password:
        raise ValueError("Missing password")
    if not access_token:
        raise ValueError("Missing access token")
    msg = PGPMessage.from_blob(access_token)
    pk, _ = PGPKey.from_blob(key)
    if IS_PY3 and isinstance(password, bytes):
        password = password.decode()
    with pk.unlock(password) as uk:
        return bytes(uk.decrypt(msg).message)
Esempio n. 6
0
 def get_package_keycode(self,
                         package_id,
                         public_key_id=None,
                         private_key=None):
     """
     Gets the decrypted package keycode using trusted device keys.
     Trusted device must have been assigned prior to the package being uploaded.
     :param package_id: The package Id
     :param public_key_id: The public key id for the trusted device
     :param private_key: The private trusted device key
     :return:
     """
     #if path_to_keys:
     #    data = read_key_pair(path_to_keys)
     #    public_key_id = data["publicKeyId"]
     #    private_key = data["privateKey"]
     if public_key_id is None or private_key is None:
         public_key_id = self.KEY_ID
         private_key = self.KEY_PAIR
     endpoint = '/package/' + package_id + '/link/' + public_key_id
     url = self.BASE_URL + endpoint
     headers = make_headers(self.API_SECRET, self.API_KEY, endpoint)
     try:
         keycode = requests.get(url, headers=headers).json()["message"]
         key_pair = pgpy.PGPKey.from_blob(str(private_key))[0]
         keycode_message = PGPMessage.from_blob(keycode)
         decrypted_keycode = key_pair.decrypt(keycode_message).message
         return {"keyCode": decrypted_keycode}
     except Exception as e:
         raise GetKeycodeFailedException(details=str(e))
Esempio n. 7
0
 def download_and_decrypt_file(self, file_id, directory_id=None, download_directory=".", file_name=None, progress_instance=None):
     """
     Downloads & decrypts the specified file to the path specified
     """
     self._block_operation_without_keycode()
     file_info = self.get_file_information(file_id)
     if not file_name:
         file_name = file_info["fileName"]
     total = file_info["fileParts"]
     file_path = download_directory + "/" + file_name
     passphrase = self.server_secret + self.client_secret
     progress = 1
     start, end = 1, 25
     try:
         with open(file_path, "wb") as file:
             while start <= total:
                 parts = _get_download_urls(self, file_id, directory_id, start=start, end=end)
                 for part in parts:
                     response = bytes(requests.get(url=part["url"]).content)
                     ba = bytearray()
                     ba.extend(response)
                     message = PGPMessage.from_blob(ba)
                     decrypted = message.decrypt(passphrase=passphrase).message
                     if isinstance(decrypted, str):
                         decrypted = bytes(decrypted, "utf-8")
                     file.write(decrypted)
                     self.calculate_progress(file_id, progress, total, progress_instance)
                     progress = progress + 1
                 start, end = start + 25, end + 25
     except Exception as e:
         raise DownloadFileException(details=str(e))
Esempio n. 8
0
def test_decrypt_unsigned_message():
    from pgpy import PGPKey, PGPMessage
    from pgpy.errors import PGPError

    # these keys are small because the regression test doesn't really need the security
    # if you're reading this, *DO NOT GENERATE RSA KEYS THIS SMALL*
    # also, it's probably better to sign-then-encrypt rather than encrypt-then-sign
    decrypt_key = "-----BEGIN PGP PRIVATE KEY BLOCK-----\n" \
                  "Version: PGPy v0.4.2\n" \
                  "\n" \
                  "xcA4BFlKzk4BAgDL9E6Lpzq9yNhRP49HXeOSYTz4DPI1A2wxwI97qjZFsJ2lJ2aV\n" \
                  "SYFpbuS6DEPaya+98HQ6xM7o2PhbUnHqcXHzABEBAAEAAf9U/XOVwpQ57e4mvWPJ\n" \
                  "i5h/sUGk5FAyQ0Dc4q9oCyAenaIIe5npbsR+oKmUHwJ5wWgfrTaxvAkBl15kMtSN\n" \
                  "VItBAQDv/8BdIdW2Bc9+qvCtC2xiUJ/3Rd+eyXMZhn4VMdA8sQEA2Y1aRBpWjHo9\n" \
                  "g9KydxAewt8LUwchRHeonMmILuZ58eMBALP8euss11ELnjDOLrgRP2swnOTTTk3b\n" \
                  "P6aV8/rbcEXOUgPNG1JlZ3Jlc3NvIEVuY3J5cHRlciAoUFIjMTgzKcJrBBMBAgAV\n" \
                  "BQJZSs6CAhsOAgsHAhUCAhYAAh4BAAoJEA2I8KkOVzh/+IMCAI308quFk/lJXPF/\n" \
                  "bpvwwgFa9bRdIzl07Qu+3oQcEm+1cu6ivznewIEmQclSUpSLjXrS/LysQSAQye+J\n" \
                  "PgSEalQ=\n" \
                  "=Sg/Y\n" \
                  "-----END PGP PRIVATE KEY BLOCK-----\n"
    sign_key = "-----BEGIN PGP PRIVATE KEY BLOCK-----\n" \
               "Version: PGPy v0.4.2\n" \
               "\n" \
               "xcA4BFlKzkMBAgDQZA3bao1qo3XkuUDOaFm1x5TkAAMUUUxtmj+dSR0wl7uRzxWm\n" \
               "8naFpsJ1Mah/I8RlS1oZizaDI7BzbOvGUGjLABEBAAEAAf95RBAQQ/QhPxfmzqrY\n" \
               "sj6qGocZGqywERMxoJYuOBLFaCjdT8xk0syI0LOCetwDmUWerUPWO52w9T5Gj295\n" \
               "YUDpAQD7DSmifDMssvG5F9JYWdKobEwWxVsjyaYR/vbH/1Iy3QEA1H+e66Jz1ERl\n" \
               "yPLyl4E5chwO2l+VMxiFod3Dvo8C68cA/0GWJIdK0NzSNZwS6wFabZg2R1pZWxJJ\n" \
               "B0tsI0EqbUgNTiXNGFJlZ3Jlc3NvIFNpZ25lciAoUFIjMTgzKcJoBBMBAgASBQJZ\n" \
               "Ss53AhsCAhUCAhYAAh4BAAoJED6S3OqHJjksTzQCAM73UuXFtM2qXp4zfOGYEMsj\n" \
               "gcKFuFFLyNOhPZo6REeJC7o2+9d7Mwys8wVNTuS3D3o1h49QpYYNjYlgNSZ85pU=\n" \
               "=DBkI\n" \
               "-----END PGP PRIVATE KEY BLOCK-----\n"

    msg = "-----BEGIN PGP MESSAGE-----\n" \
          "Version: PGPy v0.4.2\n" \
          "\n" \
          "xA0DAAIBPpLc6ocmOSwAwUwDDYjwqQ5XOH8BAfwOTH6C/lk5bQevArYnrf0q3Dde\n" \
          "JDjM/otBckiTS8kvFz1XFfQhIDkZl+fDcRwDFNe9+JKLqOM4jU6FIUwToYgz0ksB\n" \
          "f6iZ80U0dzHGtvmEzYSnsYWAglik0ch/E9tyNq/lryrLnrxWu7V26wPfI1TISuKd\n" \
          "U+w1HPGoH8ugo6GkeqBdeED6gJfKEm1qgrHCXAQAAQIABgUCWUrVMQAKCRA+ktzq\n" \
          "hyY5LLcHAgDHYjKVbpd5/FV4+CZ0H5yTnrD/vZ+QebDC7CmOM7f1Q5L1AdG/K1rr\n" \
          "+Ud/YHq3NVk5UGU0LDfjdBwVaJmOjEUx\n" \
          "=ITfp\n" \
          "-----END PGP MESSAGE-----\n"

    dkey, _ = PGPKey.from_blob(decrypt_key)
    skey, _ = PGPKey.from_blob(sign_key)
    encmsg = PGPMessage.from_blob(msg)

    # this should work
    decmsg = dkey.decrypt(encmsg)
    assert decmsg.message == "Regression Test for PR#183"

    # this should raise PGPError, not PGPDecryptionError
    with pytest.raises(PGPError):
        skey.decrypt(encmsg)
Esempio n. 9
0
def test_decrypt_unsigned_message():
    from pgpy import PGPKey, PGPMessage
    from pgpy.errors import PGPError

    # these keys are small because the regression test doesn't really need the security
    # if you're reading this, *DO NOT GENERATE RSA KEYS THIS SMALL*
    # also, it's probably better to sign-then-encrypt rather than encrypt-then-sign
    decrypt_key = "-----BEGIN PGP PRIVATE KEY BLOCK-----\n" \
                  "Version: PGPy v0.4.2\n" \
                  "\n" \
                  "xcA4BFlKzk4BAgDL9E6Lpzq9yNhRP49HXeOSYTz4DPI1A2wxwI97qjZFsJ2lJ2aV\n" \
                  "SYFpbuS6DEPaya+98HQ6xM7o2PhbUnHqcXHzABEBAAEAAf9U/XOVwpQ57e4mvWPJ\n" \
                  "i5h/sUGk5FAyQ0Dc4q9oCyAenaIIe5npbsR+oKmUHwJ5wWgfrTaxvAkBl15kMtSN\n" \
                  "VItBAQDv/8BdIdW2Bc9+qvCtC2xiUJ/3Rd+eyXMZhn4VMdA8sQEA2Y1aRBpWjHo9\n" \
                  "g9KydxAewt8LUwchRHeonMmILuZ58eMBALP8euss11ELnjDOLrgRP2swnOTTTk3b\n" \
                  "P6aV8/rbcEXOUgPNG1JlZ3Jlc3NvIEVuY3J5cHRlciAoUFIjMTgzKcJrBBMBAgAV\n" \
                  "BQJZSs6CAhsOAgsHAhUCAhYAAh4BAAoJEA2I8KkOVzh/+IMCAI308quFk/lJXPF/\n" \
                  "bpvwwgFa9bRdIzl07Qu+3oQcEm+1cu6ivznewIEmQclSUpSLjXrS/LysQSAQye+J\n" \
                  "PgSEalQ=\n" \
                  "=Sg/Y\n" \
                  "-----END PGP PRIVATE KEY BLOCK-----\n"
    sign_key = "-----BEGIN PGP PRIVATE KEY BLOCK-----\n" \
               "Version: PGPy v0.4.2\n" \
               "\n" \
               "xcA4BFlKzkMBAgDQZA3bao1qo3XkuUDOaFm1x5TkAAMUUUxtmj+dSR0wl7uRzxWm\n" \
               "8naFpsJ1Mah/I8RlS1oZizaDI7BzbOvGUGjLABEBAAEAAf95RBAQQ/QhPxfmzqrY\n" \
               "sj6qGocZGqywERMxoJYuOBLFaCjdT8xk0syI0LOCetwDmUWerUPWO52w9T5Gj295\n" \
               "YUDpAQD7DSmifDMssvG5F9JYWdKobEwWxVsjyaYR/vbH/1Iy3QEA1H+e66Jz1ERl\n" \
               "yPLyl4E5chwO2l+VMxiFod3Dvo8C68cA/0GWJIdK0NzSNZwS6wFabZg2R1pZWxJJ\n" \
               "B0tsI0EqbUgNTiXNGFJlZ3Jlc3NvIFNpZ25lciAoUFIjMTgzKcJoBBMBAgASBQJZ\n" \
               "Ss53AhsCAhUCAhYAAh4BAAoJED6S3OqHJjksTzQCAM73UuXFtM2qXp4zfOGYEMsj\n" \
               "gcKFuFFLyNOhPZo6REeJC7o2+9d7Mwys8wVNTuS3D3o1h49QpYYNjYlgNSZ85pU=\n" \
               "=DBkI\n" \
               "-----END PGP PRIVATE KEY BLOCK-----\n"

    msg = "-----BEGIN PGP MESSAGE-----\n" \
          "Version: PGPy v0.4.2\n" \
          "\n" \
          "xA0DAAIBPpLc6ocmOSwAwUwDDYjwqQ5XOH8BAfwOTH6C/lk5bQevArYnrf0q3Dde\n" \
          "JDjM/otBckiTS8kvFz1XFfQhIDkZl+fDcRwDFNe9+JKLqOM4jU6FIUwToYgz0ksB\n" \
          "f6iZ80U0dzHGtvmEzYSnsYWAglik0ch/E9tyNq/lryrLnrxWu7V26wPfI1TISuKd\n" \
          "U+w1HPGoH8ugo6GkeqBdeED6gJfKEm1qgrHCXAQAAQIABgUCWUrVMQAKCRA+ktzq\n" \
          "hyY5LLcHAgDHYjKVbpd5/FV4+CZ0H5yTnrD/vZ+QebDC7CmOM7f1Q5L1AdG/K1rr\n" \
          "+Ud/YHq3NVk5UGU0LDfjdBwVaJmOjEUx\n" \
          "=ITfp\n" \
          "-----END PGP MESSAGE-----\n"

    dkey, _ = PGPKey.from_blob(decrypt_key)
    skey, _ = PGPKey.from_blob(sign_key)
    encmsg = PGPMessage.from_blob(msg)

    # this should work
    decmsg = dkey.decrypt(encmsg)
    assert decmsg.message == "Regression Test for PR#183"

    # this should raise PGPError, not PGPDecryptionError
    with pytest.raises(PGPError):
        skey.decrypt(encmsg)
Esempio n. 10
0
 def decrypt(self, enc_data):
     if isinstance(enc_data, str):
         enc_msg = PGPMessage.from_blob(enc_data)
     else:
         enc_msg = enc_data
     keyhandle = enc_msg.issuers.pop()
     skey = self._get_key_from_keyhandle(keyhandle)
     out = skey.decrypt(enc_msg)
     keyinfos = []
     keyinfos.append(
         KeyInfo(skey.key_algorithm.name, skey.key_size,
                 skey.fingerprint.keyid, skey.userids[0].name,
                 skey.created))
     return six.b(out.message), keyinfos
Esempio n. 11
0
def _decrypt_message(message_to_decrypt, server_secret, client_secret):
    """
    Decrypts a message
    :param message_to_decrypt: The string you'd like decrypted.
    :param server_secret: The server secret, obtained by inspecting a package
    :param client_secret: The client_secret (a.k.a. keycode) used to ensure only the holders of the link
    are able to decrypt.
    :return: The decrypted message.
    """
    passphrase = server_secret + client_secret
    message_bytes = base64.b64decode(bytes(message_to_decrypt, 'utf-8'))
    pgpmessage = PGPMessage.from_blob(message_bytes)
    decrypted = pgpmessage.decrypt(passphrase=passphrase).message
    return decrypted
Esempio n. 12
0
def decrypt(profile, cdata, seckey=None):
    cmsg = cdata if isinstance(cdata, PGPMessage) \
        else PGPMessage.from_blob(cdata)
    assert cmsg.is_encrypted
    if seckey is None:
        encrypter = cmsg.encrypters.pop()
        logger.debug('encrypted by %s', encrypter)
        addr = _get_addr_from_keyhandle(profile, encrypter)
        seckey = _get_seckey_from_addr(profile, addr)
        if seckey is None:
            logger.error('No secret key found to decrypt the message.')
            return None
    out = seckey.decrypt(cmsg)
    return out.message
Esempio n. 13
0
    def decrypt(self, key):
        """ Decrypts the Body and sets the DecryptedBody 
         of this message.
        
        Parameters
        ----------
        key: pgpy.PGPKey
            An unlocked PGPKey
            
        Returns
        -------
        msg: String
            The decrypted message

        """
        msg = PGPMessage.from_blob(self.Body)
        if msg.is_encrypted:
            self.DecryptedBody = key.decrypt(msg).message
        else:
            self.DecryptedBody = self.Body
        return self.DecryptedBody
Esempio n. 14
0
def _verify_keybase_signature(raw_pgp_sig_msg):
    # load the raw pgp message
    pgp_msg = PGPMessage.from_blob(raw_pgp_sig_msg)
    # load keybase's claimed public key
    # see: https://keybase.io/docs/server_security/our_merkle_key
    kb_public_key, _ = PGPKey.from_blob(KEYBASE_PGP_VERIFICATION_KEY)

    # verify it: https://pgpy.readthedocs.io/en/latest/examples.html#verifying-things
    f = io.StringIO()
    with redirect_stderr(f):
        # suppress unnecessary stdout
        verification_result = kb_public_key.verify(pgp_msg)
    if not verification_result:
        raise VerificationError(
            "API response did not verify with Keybase's public key")

    good_signatures = list(verification_result.good_signatures)
    if len(good_signatures) != 1:
        logger.error(f"good_signatures = {good_signatures}")
        raise VerificationError(
            f"Expected 1 valid signature, got {len(good_signatures)} from {specific_url}"
        )

    return json.loads(good_signatures[0].subject)
Esempio n. 15
0
def sym_decrypt(text, passphrase):
    if isinstance(text, str):
        text = PGPMessage.from_blob(text)
    pmsg = text.decrypt(passphrase)
    return pmsg
Esempio n. 16
0
 def is_encrypted(self):
     if not self.Body:
         return False
     return PGPMessage.from_blob(self.Body).is_encrypted
Esempio n. 17
0
def _decrypt(encrypted_data: str, key: PGPKey):
    encrypted_msg = PGPMessage.from_blob(encrypted_data)
    msg = key.decrypt(encrypted_msg)
    return str(msg.message)
Esempio n. 18
0
            ciphers=[
                SymmetricKeyAlgorithm.AES256, SymmetricKeyAlgorithm.AES192,
                SymmetricKeyAlgorithm.AES128
            ],
            compression=[
                CompressionAlgorithm.ZLIB, CompressionAlgorithm.BZ2,
                CompressionAlgorithm.ZIP, CompressionAlgorithm.Uncompressed
            ])

# password protect private key
key.protect("Password", SymmetricKeyAlgorithm.AES256, HashAlgorithm.SHA256)

# print private and public key
private_key = str(key)
public_key = str(key.pubkey)
print(private_key)
print(public_key)

# encrypt message using public key
message = pgpy.PGPMessage.new(" This is the message cleartext")
encryptedmessage = str(PGPKey.from_blob(public_key)[0].encrypt(message))
print(encryptedmessage)

## decrypt using private key
private_key = PGPKey.from_blob(private_key)[0]  # reads in from string format
with private_key.unlock('Password') as unlocked_private_key:
    result = unlocked_private_key.decrypt(
        PGPMessage.from_blob(encryptedmessage))
##get cleartext  to a variable
plaintext = result.message
print(plaintext)