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
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"
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'
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)
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)
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")
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))
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
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))
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
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
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)
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__
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)
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__
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)
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))
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"
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!"
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')
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)
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
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__
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!"
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
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
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))
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!"
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
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
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
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'
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
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
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
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"
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
def test_decrypt_unsupported_algorithm(self): msg = PGPMessage.from_file('tests/testdata/message.enc.twofish.asc') with pytest.raises(PGPDecryptionError): msg.decrypt("QwertyUiop")
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")
def test_decrypt_unencrypted(self): msg = PGPMessage.from_file('tests/testdata/messages/message.signed.asc') with pytest.raises(PGPError): msg.decrypt("Password")
def test_encrypt_unsupported_algorithm(self): lit = PGPMessage.new('tests/testdata/lit') with pytest.raises(PGPEncryptionError): lit.encrypt("QwertyUiop", cipher=SymmetricKeyAlgorithm.Twofish256)
def test_encrypt_insecure_cipher(self): msg = PGPMessage.new('asdf') with pytest.raises(PGPInsecureCipher): msg.encrypt('QwertyUiop', cipher=SymmetricKeyAlgorithm.IDEA)
def test_encrypt_sessionkey_wrongtype(self): msg = PGPMessage.new('asdf') with pytest.raises(TypeError): msg.encrypt('asdf', sessionkey=bytearray(b'asdf1234asdf1234'), cipher=SymmetricKeyAlgorithm.AES128)
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)
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)
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
def message(): return PGPMessage.new("This is a message!", compression=CompressionAlgorithm.Uncompressed)
def ctmessage(): return PGPMessage.new("This is a cleartext message!", cleartext=True)