def test_firmware_pass(algo):
    # test firmware decryption with wrong and correct password
    firmware = Firmware("firmwares/{}.pass.firmware.bin".format(algo), UDID)
    assert firmware.locked
    assert not firmware.unlock(WRONGPW)
    assert firmware.unlock(GOODPW)
    assert not firmware.locked

    # extract private key from firmware
    pubkey, _ = PGPKey.from_file("pubkeys/{}.pub.key.asc".format(algo))
    privkey = firmware.extract_key(pubkey)
    assert privkey is not None

    # test message decryption
    subk = get_key_with_flag(privkey, KeyFlags.EncryptCommunications)
    assert subk is not None
    enc = PGPMessage.from_file("messages/{}.enc.msg.gpg".format(algo))
    dec = subk.decrypt(enc)
    assert bytes(dec.message) == MESSAGE

    # test signature
    subk = get_key_with_flag(privkey, KeyFlags.Sign)
    assert subk is not None
    msg = PGPMessage.new(MESSAGE, compression=CompressionAlgorithm.Uncompressed)
    sig = subk.sign(msg)
    subk = get_key_with_flag(pubkey, KeyFlags.Sign)
    assert subk is not None
    assert subk.verify(MESSAGE, sig)
def test_firmware_nopass(algo):
    # extract private key from firmware
    firmware = Firmware("firmwares/{}.firmware.bin".format(algo), UDID)
    assert not firmware.locked
    pubkey, _ = PGPKey.from_file("pubkeys/{}.pub.key.asc".format(algo))
    privkey = firmware.extract_key(pubkey)
    assert privkey is not None

    # test message decryption
    subk = get_key_with_flag(privkey, KeyFlags.EncryptCommunications)
    assert subk is not None
    enc = PGPMessage.from_file("messages/{}.enc.msg.gpg".format(algo))
    dec = subk.decrypt(enc)
    assert bytes(dec.message) == MESSAGE

    # test signature: except Ed25519 which cannot be extracted
    subk = get_key_with_flag(privkey, KeyFlags.Sign)
    if algo != 'curve25519':
        assert subk is not None
        msg = PGPMessage.new(MESSAGE, compression=CompressionAlgorithm.Uncompressed)
        sig = subk.sign(msg)
        subk = get_key_with_flag(pubkey, KeyFlags.Sign)
        assert subk is not None
        assert subk.verify(MESSAGE, sig)
    else:
        assert subk is None
Ejemplo n.º 3
0
    def test_select_pgpmessage(self, keyring):
        m1 = PGPMessage()
        with open('tests/testdata/messages/message.rsa.cast5.asc', 'r') as m1f:
            m1.parse(m1f.read())

        with keyring.key(m1) as rsakey:
            assert rsakey.fingerprint == "00EC FAF5 48AE B655 F861  8193 EEE0 97A0 17B9 79CA"
            assert rsakey.parent.fingerprint == "F429 4BC8 094A 7E05 85C8 5E86 3747 3B37 58C4 4F36"
Ejemplo n.º 4
0
    def test_select_pgpmessage(self, keyring):
        m1 = PGPMessage()
        with open('tests/testdata/messages/message.rsa.cast5.asc', 'r') as m1f:
            m1.parse(m1f.read())

        with keyring.key(m1) as rsakey:
            assert rsakey.fingerprint == "00EC FAF5 48AE B655 F861  8193 EEE0 97A0 17B9 79CA"
            assert rsakey.parent.fingerprint == "F429 4BC8 094A 7E05 85C8 5E86 3747 3B37 58C4 4F36"
Ejemplo n.º 5
0
    def test_encrypt_message_select_uid(self):
        # generate a temporary key with two UIDs, then encrypt a message
        u1 = PGPUID.new('UID One')
        u2 = PGPUID.new('UID Two')
        k = PGPKey.new(PubKeyAlgorithm.RSAEncryptOrSign, 512)

        flags = {
            KeyFlags.Certify, KeyFlags.Sign, KeyFlags.EncryptCommunications,
            KeyFlags.EncryptStorage
        }

        k.add_uid(u1,
                  usage=flags,
                  hashes=[HashAlgorithm.SHA1],
                  ciphers=[SymmetricKeyAlgorithm.AES128])
        k.add_uid(u2,
                  usage=flags,
                  hashes=[HashAlgorithm.SHA1],
                  ciphers=[SymmetricKeyAlgorithm.Camellia128])

        emsg = k.pubkey.encrypt(
            PGPMessage.new('This message is about to be encrypted'),
            user='******')

        # assert that it was encrypted with Camellia128 and that we can decrypt it normally
        assert emsg._sessionkeys[0].decrypt_sk(
            k._key)[0] == SymmetricKeyAlgorithm.Camellia128
        assert k.decrypt(
            emsg).message == 'This message is about to be encrypted'
Ejemplo n.º 6
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)
Ejemplo n.º 7
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)
Ejemplo n.º 8
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")
Ejemplo n.º 9
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))
Ejemplo n.º 10
0
def sign_encrypt(profile, data, addr, recipients):
    pmsg = data if isinstance(data, PGPMessage) else PGPMessage.new(data)
    sig = sign(profile, pmsg, addr)
    pmsg |= sig
    assert pmsg.is_signed
    cmsg = encrypt(profile, pmsg, recipients)
    return cmsg
Ejemplo n.º 11
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))
Ejemplo n.º 12
0
def encrypt(profile, data, recipients):
    assert isinstance(recipients, list)
    msg = data if isinstance(data, PGPMessage) else PGPMessage.new(data)
    # pmsg |= seckey.sign(msg)
    if len(recipients) == 1:
        key = _get_pubkey_from_addr(profile, recipients[0])
        if key is None:
            logger.error('No key found to encrypt message.')
            return None
        pubkey = key if key.is_public else key.pubkey
        cmsg = pubkey.encrypt(msg)
    else:
        # The symmetric cipher should be specified, in case the first
        # preferred cipher is not the same for all recipients public
        # keys.
        cipher = SymmetricKeyAlgorithm.AES256
        sessionkey = cipher.gen_key()
        cmsg = msg
        for r in recipients:
            key = _get_pubkey_from_addr(profile, r)
            if key is None:
                logger.error('No key found to encrypt message.')
                break
            pubkey = key if key.is_public else key.pubkey
            cmsg = pubkey.encrypt(cmsg, cipher=cipher, sessionkey=sessionkey)
        del sessionkey
    return cmsg
Ejemplo n.º 13
0
    def test_encrypt_passphrase(self, comp_alg, gpg_decrypt):
        mtxt = "This message is to be encrypted"
        msg = PGPMessage.new(mtxt, compression=comp_alg)
        assert not msg.is_encrypted

        encmsg = msg.encrypt("QwertyUiop")

        assert isinstance(encmsg, PGPMessage)
        assert encmsg.is_encrypted
        assert encmsg.type == 'encrypted'

        # decrypt with PGPy
        decmsg = encmsg.decrypt("QwertyUiop")

        assert isinstance(decmsg, PGPMessage)
        assert decmsg.type == msg.type
        assert decmsg.is_compressed == msg.is_compressed
        assert decmsg.message == mtxt
        assert decmsg._compression == msg._compression

        # decrypt with GPG
        with tempfile.NamedTemporaryFile('w+') as mf:
            mf.write(str(encmsg))
            mf.flush()
            assert gpg_decrypt(mf.name, "QwertyUiop") == mtxt
Ejemplo n.º 14
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)
Ejemplo n.º 15
0
    def test_decrypt_unencrypted_message(self, rsa_sec, recwarn):
        lit = PGPMessage.new('tests/testdata/lit', file=True)
        rsa_sec.decrypt(lit)

        w = recwarn.pop(UserWarning)
        assert str(w.message) == "This message is not encrypted"
        assert w.filename == __file__
Ejemplo n.º 16
0
    def test_decrypt_unencrypted_message(self, rsa_sec, recwarn):
        lit = PGPMessage.new('tests/testdata/lit', file=True)
        rsa_sec.decrypt(lit)

        w = recwarn.pop(UserWarning)
        assert str(w.message) == "This message is not encrypted"
        assert w.filename == __file__
Ejemplo n.º 17
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)
Ejemplo n.º 18
0
    def test_sign_bad_prefs(self, rsa_sec, recwarn):
        rsa_sec.subkeys['2A834D8E5918E886'].sign(PGPMessage.new('asdf'),
                                                 hash=HashAlgorithm.RIPEMD160)

        w = recwarn.pop(UserWarning)
        assert str(
            w.message) == "Selected hash algorithm not in key preferences"
        assert w.filename == __file__
Ejemplo n.º 19
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)
Ejemplo n.º 20
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)
Ejemplo n.º 21
0
def encrypt(message: str, key: bytes) -> str:
    import pgpy
    from pgpy import PGPMessage
    from pgpy.constants import CompressionAlgorithm

    message = PGPMessage.new(message,
                             compression=CompressionAlgorithm.Uncompressed)
    pub_key, _ = pgpy.PGPKey.from_blob(key)
    return str(pub_key.encrypt(message))
Ejemplo n.º 22
0
 def test_gpg_cv25519_decrypt(self, abe):
     # test the decryption of X25519 generated by GnuPG
     seckey, _ = PGPKey.from_file('tests/testdata/keys/ecc.2.sec.asc')
     emsg = PGPMessage.from_file(
         'tests/testdata/messages/message.ecdh.cv25519.asc')
     with warnings.catch_warnings():
         warnings.simplefilter('ignore')
         dmsg = seckey.decrypt(emsg)
     assert bytes(dmsg.message) == b"This message will have been encrypted"
Ejemplo n.º 23
0
    def test_new_sensitive(self, write_clean, gpg_print):
        msg = PGPMessage.new("This is a sensitive message!", sensitive=True)

        assert msg.type == 'literal'
        assert msg.message == "This is a sensitive message!"
        assert msg.is_sensitive
        assert msg.filename == '_CONSOLE'

        with write_clean('tests/testdata/csmsg.asc', 'w', str(msg)):
            assert gpg_print('csmsg.asc') == "This is a sensitive message!"
Ejemplo n.º 24
0
    def test_new_sensitive(self, write_clean, gpg_print):
        msg = PGPMessage.new("This is a sensitive message!", sensitive=True)

        assert msg.type == 'literal'
        assert msg.message == "This is a sensitive message!"
        assert msg.is_sensitive
        assert msg.filename == '_CONSOLE'

        with write_clean('tests/testdata/csmsg.asc', 'w', str(msg)):
            assert gpg_print('csmsg.asc') == "This is a sensitive message!"
Ejemplo n.º 25
0
    def test_new_non_unicode(self, write_clean, gpg_print):
        # this message text comes from http://www.columbia.edu/~fdc/utf8/
        text = u'色は匂へど 散りぬるを\n' \
               u'我が世誰ぞ 常ならむ\n' \
               u'有為の奥山 今日越えて\n' \
               u'浅き夢見じ 酔ひもせず\n'
        msg = PGPMessage.new(text.encode('jisx0213'), encoding='jisx0213')

        assert msg.type == 'literal'
        assert msg.message == text.encode('jisx0213')
Ejemplo n.º 26
0
    def test_new_non_unicode(self, write_clean, gpg_print):
        # this message text comes from http://www.columbia.edu/~fdc/utf8/
        text = u'色は匂へど 散りぬるを\n' \
               u'我が世誰ぞ 常ならむ\n' \
               u'有為の奥山 今日越えて\n' \
               u'浅き夢見じ 酔ひもせず\n'
        msg = PGPMessage.new(text.encode('jisx0213'), encoding='jisx0213')

        assert msg.type == 'literal'
        assert msg.message == text.encode('jisx0213')
Ejemplo n.º 27
0
    def test_load_from_file(self, msgfile):
        # TODO: figure out a good way to verify that all went well here, because
        #       PGPy reorders signatures sometimes, and also unwraps compressed messages
        #       so comparing str(msg) to the contents of msgfile doesn't actually work
        msg = PGPMessage.from_file(msgfile)

        with open(msgfile, 'r') as mf:
            mt = mf.read()

            assert len(str(msg)) == len(mt)
Ejemplo n.º 28
0
    def test_load_from_file(self, msgfile):
        # TODO: figure out a good way to verify that all went well here, because
        #       PGPy reorders signatures sometimes, and also unwraps compressed messages
        #       so comparing str(msg) to the contents of msgfile doesn't actually work
        msg = PGPMessage.from_file(msgfile)

        with open(msgfile, 'r') as mf:
            mt = mf.read()

            assert len(str(msg)) == len(mt)
Ejemplo n.º 29
0
    def test_new_non_unicode_cleartext(self):
        # this message text comes from http://www.columbia.edu/~fdc/utf8/
        text = u'色は匂へど 散りぬるを\n' \
               u'我が世誰ぞ 常ならむ\n' \
               u'有為の奥山 今日越えて\n' \
               u'浅き夢見じ 酔ひもせず'
        msg = PGPMessage.new(text.encode('jisx0213'), cleartext=True, encoding='jisx0213')

        assert msg.type == 'cleartext'
        assert msg.message == text
Ejemplo n.º 30
0
    def test_encrypt_bad_cipher(self, rsa_pub, recwarn):
        rsa_pub.subkeys['EEE097A017B979CA'].encrypt(PGPMessage.new('asdf'),
                                                    cipher=SymmetricKeyAlgorithm.CAST5)

        w = recwarn.pop(UserWarning)
        assert str(w.message) == "Selected symmetric algorithm not in key preferences"
        assert w.filename == __file__

        w = recwarn.pop(UserWarning)
        assert str(w.message) == "Selected compression algorithm not in key preferences"
        assert w.filename == __file__
Ejemplo n.º 31
0
    def test_new(self, comp_alg, write_clean, gpg_print):
        msg = PGPMessage.new(u"This is a new message!", compression=comp_alg)

        assert msg.filename == ''
        assert msg.type == 'literal'
        assert msg.message == u"This is a new message!"
        assert msg._message.format == 'u'
        assert msg._message.filename == ''
        assert msg.is_compressed is bool(comp_alg != CompressionAlgorithm.Uncompressed)

        with write_clean('tests/testdata/cmsg.asc', 'w', str(msg)):
            assert gpg_print('cmsg.asc') == "This is a new message!"
Ejemplo n.º 32
0
    def test_new_non_unicode_cleartext(self):
        # this message text comes from http://www.columbia.edu/~fdc/utf8/
        text = u'色は匂へど 散りぬるを\n' \
               u'我が世誰ぞ 常ならむ\n' \
               u'有為の奥山 今日越えて\n' \
               u'浅き夢見じ 酔ひもせず'
        msg = PGPMessage.new(text.encode('jisx0213'),
                             cleartext=True,
                             encoding='jisx0213')

        assert msg.type == 'cleartext'
        assert msg.message == text
Ejemplo n.º 33
0
    def test_encrypt_message(self, pub, cipher):
        if pub.key_algorithm in {PubKeyAlgorithm.DSA}:
            pytest.skip('Asymmetric encryption only implemented for RSA/ECDH currently')

        if cipher in {SymmetricKeyAlgorithm.Plaintext, SymmetricKeyAlgorithm.Twofish256, SymmetricKeyAlgorithm.IDEA}:
            pytest.xfail('Symmetric cipher {} not supported for encryption'.format(cipher))

        # test encrypting a message
        mtxt = "This message will have been encrypted"
        msg = PGPMessage.new(mtxt)
        emsg = pub.encrypt(msg, cipher=cipher)
        self.msgs[(pub.fingerprint, cipher)] = emsg
Ejemplo n.º 34
0
    def test_encrypt_message(self, pub, cipher):
        if pub.key_algorithm in {PubKeyAlgorithm.DSA}:
            pytest.skip('Asymmetric encryption only implemented for RSA/ECDH currently')

        if cipher in {SymmetricKeyAlgorithm.Plaintext, SymmetricKeyAlgorithm.Twofish256, SymmetricKeyAlgorithm.IDEA}:
            pytest.xfail('Symmetric cipher {} not supported for encryption'.format(cipher))

        # test encrypting a message
        mtxt = "This message will have been encrypted"
        msg = PGPMessage.new(mtxt)
        emsg = pub.encrypt(msg, cipher=cipher)
        self.msgs[(pub.fingerprint, cipher)] = emsg
Ejemplo n.º 35
0
    def test_new(self, comp_alg, sensitive):
        mtxt = u"This is a new message!"
        msg = PGPMessage.new(mtxt, compression=comp_alg, sensitive=sensitive)

        assert isinstance(msg, PGPMessage)
        assert msg.filename == ('_CONSOLE' if sensitive else '')
        assert msg.is_sensitive is sensitive
        assert msg.type == 'literal'
        assert msg.message == mtxt
        assert msg._compression == comp_alg

        # see if GPG can parse our message
        assert self.gpg_message(msg).decode('utf-8') == mtxt
Ejemplo n.º 36
0
    def test_new(self, comp_alg, sensitive):
        mtxt = u"This is a new message!"
        msg = PGPMessage.new(mtxt, compression=comp_alg, sensitive=sensitive)

        assert isinstance(msg, PGPMessage)
        assert msg.filename == ('_CONSOLE' if sensitive else '')
        assert msg.is_sensitive is sensitive
        assert msg.type == 'literal'
        assert msg.message == mtxt
        assert msg._compression == comp_alg

        # see if GPG can parse our message
        assert self.gpg_message(msg).decode('utf-8') == mtxt
Ejemplo n.º 37
0
def main():

    parser = argparse.ArgumentParser(
        description='''Encrypting a relatively small message''')
    parser.add_argument('pubkey', help='PGP public key')
    parser.add_argument('file', help='File to encrypt')
    args = parser.parse_args()

    message = PGPMessage.new(args.file, file=True)
    key, _ = PGPKey.from_file(args.pubkey)

    enc = key.encrypt(message)
    sys.stdout.buffer.write(bytes(enc))
Ejemplo n.º 38
0
    def test_new(self, comp_alg, write_clean, gpg_print):
        msg = PGPMessage.new(u"This is a new message!", compression=comp_alg)

        assert msg.filename == ''
        assert msg.type == 'literal'
        assert msg.message == u"This is a new message!"
        assert msg._message.format == 'u'
        assert msg._message.filename == ''
        assert msg.is_compressed is bool(
            comp_alg != CompressionAlgorithm.Uncompressed)

        with write_clean('tests/testdata/cmsg.asc', 'w', str(msg)):
            assert gpg_print('cmsg.asc') == "This is a new message!"
Ejemplo n.º 39
0
    def test_new_non_unicode(self):
        # this message text comes from http://www.columbia.edu/~fdc/utf8/
        text = u'色は匂へど 散りぬるを\n' \
               u'我が世誰ぞ 常ならむ\n' \
               u'有為の奥山 今日越えて\n' \
               u'浅き夢見じ 酔ひもせず'
        msg = PGPMessage.new(text.encode('jisx0213'), encoding='jisx0213')

        assert msg.type == 'literal'
        assert msg.message == text.encode('jisx0213')

        # see if GPG can parse our message
        assert self.gpg_message(msg).decode('jisx0213') == text
Ejemplo n.º 40
0
    def test_new_non_unicode(self):
        # this message text comes from http://www.columbia.edu/~fdc/utf8/
        text = u'色は匂へど 散りぬるを\n' \
               u'我が世誰ぞ 常ならむ\n' \
               u'有為の奥山 今日越えて\n' \
               u'浅き夢見じ 酔ひもせず'
        msg = PGPMessage.new(text.encode('jisx0213'), encoding='jisx0213')

        assert msg.type == 'literal'
        assert msg.message == text.encode('jisx0213')

        # see if GPG can parse our message
        assert self.gpg_message(msg).decode('jisx0213') == text
Ejemplo n.º 41
0
    def test_new_from_file(self, comp_alg, sensitive, path):
        msg = PGPMessage.new(path, file=True, compression=comp_alg, sensitive=sensitive)

        assert isinstance(msg, PGPMessage)
        assert msg.filename == ('_CONSOLE' if sensitive else os.path.basename(path))
        assert msg.type == 'literal'
        assert msg.is_sensitive is sensitive

        with open(path, 'rb') as tf:
            mtxt = tf.read()

            # see if GPG can parse our message
            assert self.gpg_message(msg) == mtxt
Ejemplo n.º 42
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
Ejemplo n.º 43
0
    def test_encrypt_message_select_uid(self):
        # generate a temporary key with two UIDs, then encrypt a message
        u1 = PGPUID.new('UID One')
        u2 = PGPUID.new('UID Two')
        k = PGPKey.new(PubKeyAlgorithm.RSAEncryptOrSign, 512)

        flags = {KeyFlags.Certify, KeyFlags.Sign, KeyFlags.EncryptCommunications, KeyFlags.EncryptStorage}

        k.add_uid(u1, usage=flags, hashes=[HashAlgorithm.SHA1], ciphers=[SymmetricKeyAlgorithm.AES128])
        k.add_uid(u2, usage=flags, hashes=[HashAlgorithm.SHA1], ciphers=[SymmetricKeyAlgorithm.Camellia128])

        emsg = k.pubkey.encrypt(PGPMessage.new('This message is about to be encrypted'), user='******')

        # assert that it was encrypted with Camellia128 and that we can decrypt it normally
        assert emsg._sessionkeys[0].decrypt_sk(k._key)[0] == SymmetricKeyAlgorithm.Camellia128
        assert k.decrypt(emsg).message == 'This message is about to be encrypted'
Ejemplo n.º 44
0
    def test_new_from_file(self, file, write_clean, gpg_print):
        msg = PGPMessage.new(file, file=True)

        assert isinstance(msg, PGPMessage)
        assert msg.type == 'literal'
        assert msg.is_sensitive is False

        assert file in self.attrs
        for attr, expected in self.attrs[file]:
            val = getattr(msg, attr)
            assert val == expected

        with write_clean('tests/testdata/cmsg.asc', 'w', str(msg)):
            out = gpg_print('cmsg.asc')
            if msg._message.format == 'b':
                out = out.encode('latin-1')
            assert out == msg.message
Ejemplo n.º 45
0
    def test_encrypt_passphrase_2(self):
        mtxt = "This message is to be encrypted"
        msg = PGPMessage.new(mtxt)
        assert not msg.is_encrypted

        sk = SymmetricKeyAlgorithm.AES256.gen_key()
        encmsg = msg.encrypt("QwertyUiop", sessionkey=sk).encrypt("AsdfGhjkl", sessionkey=sk)

        assert isinstance(encmsg, PGPMessage)
        assert encmsg.is_encrypted
        assert encmsg.type == 'encrypted'

        # decrypt with PGPy only, since GnuPG can't do multiple passphrases
        for passwd in ["QwertyUiop", "AsdfGhjkl"]:
            decmsg = encmsg.decrypt(passwd)

            assert isinstance(decmsg, PGPMessage)
            assert decmsg.type == msg.type
            assert decmsg.is_compressed
            assert decmsg.message == mtxt
Ejemplo n.º 46
0
    def test_encrypt_passphrase_2(self, write_clean, gpg_decrypt):
        msg = PGPMessage.new("This message is to be encrypted")
        sk = SymmetricKeyAlgorithm.AES256.gen_key()
        encmsg = msg.encrypt("QwertyUiop", sessionkey=sk).encrypt("AsdfGhjkl", sessionkey=sk)

        # make sure lit was untouched
        assert not msg.is_encrypted

        # make sure encmsg is encrypted
        assert encmsg.is_encrypted
        assert encmsg.type == 'encrypted'
        assert len(encmsg._sessionkeys) == 2

        # decrypt with PGPy
        for passphrase in ["QwertyUiop", "AsdfGhjkl"]:
            decmsg = encmsg.decrypt(passphrase)
            assert isinstance(decmsg, PGPMessage)
            assert decmsg.type == msg.type
            assert decmsg.is_compressed
            assert decmsg.message == msg.message
Ejemplo n.º 47
0
    def test_encrypt_passphrase(self, write_clean, gpg_decrypt):
        msg = PGPMessage.new("This message is to be encrypted")
        encmsg = msg.encrypt("QwertyUiop")

        # make sure lit was untouched
        assert not msg.is_encrypted

        # make sure encmsg is encrypted
        assert encmsg.is_encrypted
        assert encmsg.type == 'encrypted'

        # decrypt with PGPy
        decmsg = encmsg.decrypt("QwertyUiop")

        assert isinstance(decmsg, PGPMessage)
        assert decmsg.type == msg.type
        assert decmsg.is_compressed
        assert decmsg.message == msg.message

        # decrypt with GPG
        with write_clean('tests/testdata/semsg.asc', 'w', str(encmsg)):
            assert gpg_decrypt('./semsg.asc', "QwertyUiop") == "This message is to be encrypted"
Ejemplo n.º 48
0
    def test_encrypt_passphrase(self, comp_alg):
        mtxt = "This message is to be encrypted"
        msg = PGPMessage.new(mtxt, compression=comp_alg)
        assert not msg.is_encrypted

        encmsg = msg.encrypt("QwertyUiop")

        assert isinstance(encmsg, PGPMessage)
        assert encmsg.is_encrypted
        assert encmsg.type == 'encrypted'

        # decrypt with PGPy
        decmsg = encmsg.decrypt("QwertyUiop")

        assert isinstance(decmsg, PGPMessage)
        assert decmsg.type == msg.type
        assert decmsg.is_compressed == msg.is_compressed
        assert decmsg.message == mtxt
        assert decmsg._compression == msg._compression

        # decrypt with GPG via python-gnupg
        assert self.gpg_decrypt(encmsg, 'QwertyUiop').decode('utf-8') == decmsg.message
Ejemplo n.º 49
0
 def test_decrypt_unsupported_algorithm(self):
     msg = PGPMessage.from_file('tests/testdata/message.enc.twofish.asc')
     with pytest.raises(PGPDecryptionError):
         msg.decrypt("QwertyUiop")
Ejemplo n.º 50
0
 def test_decrypt_wrongpass(self):
     msg = PGPMessage.from_file(next(f for f in glob.glob('tests/testdata/messages/message*.pass*.asc')))
     with pytest.raises(PGPDecryptionError):
         msg.decrypt("TheWrongPassword")
Ejemplo n.º 51
0
 def test_decrypt_unencrypted(self):
     msg = PGPMessage.from_file('tests/testdata/messages/message.signed.asc')
     with pytest.raises(PGPError):
         msg.decrypt("Password")
Ejemplo n.º 52
0
 def test_encrypt_unsupported_algorithm(self):
     lit = PGPMessage.new('tests/testdata/lit')
     with pytest.raises(PGPEncryptionError):
         lit.encrypt("QwertyUiop", cipher=SymmetricKeyAlgorithm.Twofish256)
Ejemplo n.º 53
0
 def test_encrypt_insecure_cipher(self):
     msg = PGPMessage.new('asdf')
     with pytest.raises(PGPInsecureCipher):
         msg.encrypt('QwertyUiop', cipher=SymmetricKeyAlgorithm.IDEA)
Ejemplo n.º 54
0
 def test_encrypt_sessionkey_wrongtype(self):
     msg = PGPMessage.new('asdf')
     with pytest.raises(TypeError):
         msg.encrypt('asdf', sessionkey=bytearray(b'asdf1234asdf1234'), cipher=SymmetricKeyAlgorithm.AES128)
Ejemplo n.º 55
0
 def test_parse_wrong_magic(self):
     msgtext = _read('tests/testdata/messages/message.signed.asc').replace('MESSAGE', 'EMSSAGE')
     msg = PGPMessage()
     with pytest.raises(ValueError):
         msg.parse(msgtext)
Ejemplo n.º 56
0
from pgpy.constants import CompressionAlgorithm
from pgpy.constants import EllipticCurveOID
from pgpy.constants import Features
from pgpy.constants import HashAlgorithm
from pgpy.constants import KeyFlags
from pgpy.constants import KeyServerPreferences
from pgpy.constants import PubKeyAlgorithm
from pgpy.constants import RevocationReason
from pgpy.constants import SignatureType
from pgpy.constants import SymmetricKeyAlgorithm
from pgpy.packet import Packet
from pgpy.packet.packets import PrivKeyV4
from pgpy.packet.packets import PrivSubKeyV4


enc_msgs = [ PGPMessage.from_file(f) for f in sorted(glob.glob('tests/testdata/messages/message*.pass*.asc')) ]


class TestPGPMessage(object):
    @staticmethod
    def gpg_message(msg):
        with gpg.Context(offline=True) as c:
            c.set_engine_info(gpg.constants.PROTOCOL_OpenPGP, home_dir=gnupghome)
            msg, _ = c.verify(gpg.Data(string=str(msg)))
        return msg

    @staticmethod
    def gpg_decrypt(msg, passphrase):
        try:
            with gpg.Context(armor=True, offline=True, pinentry_mode=gpg.constants.PINENTRY_MODE_LOOPBACK) as c:
                c.set_engine_info(gpg.constants.PROTOCOL_OpenPGP, file_name='/usr/bin/gpg', home_dir=gnupghome)
Ejemplo n.º 57
0
 def test_add_marker(self):
     msg = PGPMessage.new(u"This is a new message")
     marker = Packet(bytearray(b'\xa8\x03\x50\x47\x50'))
     msg |= marker
Ejemplo n.º 58
0
def message():
    return PGPMessage.new("This is a message!", compression=CompressionAlgorithm.Uncompressed)
Ejemplo n.º 59
0
def ctmessage():
    return PGPMessage.new("This is a cleartext message!", cleartext=True)