def abe(): uid = PGPUID.new('Abraham Lincoln', comment='Honest Abe', email='*****@*****.**') with open('tests/testdata/abe.jpg', 'rb') as abef: abebytes = bytearray(os.fstat(abef.fileno()).st_size) abef.readinto(abebytes) uphoto = PGPUID.new(abebytes) # Abe is pretty oldschool, so he uses a DSA primary key # normally he uses an ElGamal subkey for encryption, but PGPy doesn't support that yet, so he's settled for RSA for now key = PGPKey.new(PubKeyAlgorithm.DSA, 1024) subkey = PGPKey.new(PubKeyAlgorithm.RSAEncryptOrSign, 1024) key.add_uid(uid, usage={KeyFlags.Certify, KeyFlags.Sign}, hashes=[HashAlgorithm.SHA224, HashAlgorithm.SHA1], ciphers=[ SymmetricKeyAlgorithm.AES128, SymmetricKeyAlgorithm.Camellia128, SymmetricKeyAlgorithm.CAST5 ], compression=[CompressionAlgorithm.ZLIB]) key.add_uid(uphoto) key.add_subkey( subkey, usage={KeyFlags.EncryptCommunications, KeyFlags.EncryptStorage}) return key
def _verify_and_import_uid_packet(self, primary_key: PGPKey, uid_packet: bytes, expected_hash: str) -> None: actual_serialized_hash = sha256(uid_packet).hex() if not actual_serialized_hash == expected_hash: # hashes for the content do not match return imported_key, _ = PGPKey.from_blob(uid_packet) if not imported_key.fingerprint == primary_key.fingerprint: # Primary key material on the two keys does not match. They don't belong together. return if not KeyStore._verify_legal_key_with_single_userid(imported_key): # key failed one of the validity tests return if not primary_key.verify(imported_key.userids[0]): # Primary key did not sign userid. # This check was already performed via the self-signature check on imported_key and the fingerprint # match with primary_key before. return new_userid: PGPUID = imported_key.userids[0] self._transplant_uid(new_userid, primary_key)
def create_app(test_config=None): app = Flask(__name__, instance_relative_config=True) ca_pub_key, _ = PGPKey.from_file( os.path.join(app.root_path, '..', 'key', 'pub.asc')) ca_sec_key, _ = PGPKey.from_file( os.path.join(app.root_path, '..', 'key', 'sec.asc')) assert ca_sec_key.is_protected assert ca_sec_key.is_unlocked is False app.config.from_mapping( SECRET_KEY='sooO0O0Oo0O0oo0OoOOo-s3cur3', CA_PUB_KEY=ca_pub_key, CA_SEC_KEY=ca_sec_key, CA_PASSPHRASE='is521xyz!', DB=os.path.join(app.instance_path, 'ca.db'), ) try: os.makedirs(app.instance_path) except OSError: pass app.register_blueprint(user.bp) app.register_blueprint(cert.bp) app.teardown_appcontext(db.close_db) if not os.path.isfile(app.config['DB']): with app.app_context(): db.init_db() return app
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 test_save(self, kf): # load the key and export it back to binary key, _ = PGPKey.from_file(kf) pgpyblob = key.__bytes__() # try loading the exported key reloaded, _ = PGPKey.from_file(kf) assert pgpyblob == reloaded.__bytes__()
def temp_key(): u = PGPUID.new('User') k = PGPKey.new(PubKeyAlgorithm.RSAEncryptOrSign, 512) k.add_uid(u, usage={KeyFlags.Certify, KeyFlags.Sign}, hashes=[HashAlgorithm.SHA1]) sk = PGPKey.new(PubKeyAlgorithm.RSAEncryptOrSign, 512) k.add_subkey(sk, usage={KeyFlags.EncryptCommunications}) return k
def test_parse_wrong_crc24(self, recwarn): keytext = _read('tests/testdata/keys/rsa.1.sec.asc').splitlines() keytext[-2] = "=abcd" keytext = '\n'.join(keytext) key = PGPKey() key.parse(keytext) w = recwarn.pop(UserWarning) assert str(w.message) == "Incorrect crc24" assert w.filename == __file__
def generate_rsa_key(uid='*****@*****.**', alg_key=PubKeyAlgorithm.RSAEncryptOrSign, alg_subkey=PubKeyAlgorithm.RSAEncryptOrSign, size=2048): # RSAEncrypt is deprecated, therefore using RSAEncryptOrSign # also for the subkey """Generate PGPKey object. :param alg_key: algorithm for primary key :param alg_subkey: algorithm for subkey :param size: key size :param uid: e-mail address :return: key :type alg_key: PubKeyAlgorithm :type alg_subkey: PubKeyAlgorithm :type size: integer :type uid: string :rtype: PGPKey """ # NOTE: default algorithm was decided to be RSA and size 2048. key = PGPKey.new(alg_key, size) # NOTE: pgpy implements separate attributes for name and e-mail address # is mandatory. # Here using e-mail address for the attribute name in order for # the uid to be the e-mail address. If name attribute is set to # empty string and email to the e-mail address, the uid will be ' # <e-mail address>', for instance: # " <*****@*****.**>" - which we do not want. uid = PGPUID.new(uid) # NOTE: it is needed to specify all arguments in current pgpy version. # FIXME: see which defaults we would like here key.add_uid(uid, usage={KeyFlags.Sign}, hashes=[HashAlgorithm.SHA512, HashAlgorithm.SHA256], ciphers=[ SymmetricKeyAlgorithm.AES256, SymmetricKeyAlgorithm.AES192, SymmetricKeyAlgorithm.AES128 ], compression=[ CompressionAlgorithm.ZLIB, CompressionAlgorithm.BZ2, CompressionAlgorithm.ZIP, CompressionAlgorithm.Uncompressed ]) subkey = PGPKey.new(alg_subkey, size) key.add_subkey( subkey, usage={KeyFlags.EncryptCommunications, KeyFlags.EncryptStorage}) logger.debug('Created key with fingerprint %s', key.fingerprint) return key
def test_pubkey_subkey_parent(): from pgpy import PGPKey # import this small key that has a subkey keyblob = ('-----BEGIN PGP PRIVATE KEY BLOCK-----\n' 'Version: PGPy v0.4.2\n' '\n' 'xcA4BFlULU4BAgDeq2bKPPOBzdgd1WF3RBQ0E0kkZbTfpgZjamDzdb6gfQ5TcBhs\n' 'drI4XpxWOV3DorbsZ8Usj4zHx/XmLNCmxwqvABEBAAEAAgCSO76l0qGY/baQ4THB\n' 'QdSC3qeKX8EJn99SKurA+PLYMg6IxLGBpWYIK8tT68xpqQ5ZwE9GodZ2QjfOVz2R\n' 'o4IBAQD/UjtthEtyiMA1CDCPEksfIyd0QDjt82C19MSeqau8WQEA30LydxkjlvgH\n' 'u5/uWVGqoFWhhfw5hDrYy72L6EbCfkcA/2csk7uGw/yg2MDUTlDwdokn1DLGkt/+\n' 'Q/fPAMYvX6gvVoXNFVJlZ3Jlc3NvIChJc3N1ZSAjMTk0KcJrBBMBAgAVBQJZVC3O\n' 'AhsDAgsHAhUCAhYAAh4BAAoJEC4sMTkKIj+F8ywB/AqaNHwi8xM1Rg99mOSib1zi\n' 'jlXALY8pOrNU7Nqtc/6oks+49WeVW5zpE1vl1JPm2WYzvCEnE1KffdyjNR0bQ1XH\n' 'wDgEWVQtUQECAKsWCdSRh6YDP9yuSonfHpBfUzRD/EQvpNnUDiTclV9w6RPMZYk9\n' 'o5oUQTumPKnznsovLpNmIm48DCALMzdTzH0AEQEAAQACAJDfsKNYOM3Toph03pmx\n' 'XmhS0FpJ16zFy4rJjtCYGcUerUqRQ1ehXIY9Ig9J5LitJXThrP4dvUlRCWUcxxl6\n' '9eEBANOiM8ktXW0bPZfBKunWn7ajA0PMBKG8p2d9iBCawBbbAQDO88L8V0cxCRvH\n' '8L1J4gsttPWDOnhw5z8Dq4Zv5U3thwD/WwE0miqfEpYAmkhc0g7lHf6l7qo+SrUZ\n' 'ZKl0GLPLKKFRscK9BBgBAgAJBQJZVC3mAhsMAGgJEC4sMTkKIj+FXSAEGQECAAYF\n' 'AllULeYACgkQCK0qxtsEtqzY7QIAoayZGB78eaImQVOpTLX2jnaDR2UY7NtUy6YI\n' 'XMSumCeZj+n+BexmUm6x2kqg0FJLRwAE4i+rnvFA0HHX40/9d221AgCzUxHuHjKP\n' 'b5wNW20vanc6b6ZMi52MyhluXAIdnvgPkPEzVIS+gGOX2DeT4TXAdosKfD1o5qS7\n' 'ANRbocmpDuO3\n' '=UjzO\n' '-----END PGP PRIVATE KEY BLOCK-----\n') privkey, _ = PGPKey.from_blob(keyblob) pubkey = privkey.pubkey assert pubkey.subkeys['08AD2AC6DB04B6AC'].parent is pubkey
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 extract_key(self, pubkey): """ Build the PGP private key from the corresponding public key and this firmware key material """ assert not self.locked assert pubkey.is_public # create parent key privkey = self._create_private_key(pubkey, False) if not privkey: privkey = Firmware._nosecrete_private_key(pubkey._key) # take user IDs with their signatures from the public key for uid in pubkey.userids: privkey._uids.append(uid) # extract all sub keys for sk in pubkey.subkeys.values(): key = self._create_private_key(sk) if not key: logging.warning("Subkey not present in firmware: {}".format(sk.fingerprint)) continue privkey._children[key.fingerprint.keyid] = key key._parent = privkey # reload key so every field is correctly computed return PGPKey.from_blob(bytes(privkey))[0]
def _nosecrete_private_key(pubkey): """ Create the parent certify key without the private parts """ km = OpaquePrivKey() km.parse(pubkey.keymaterial.__bytearray__()) # S2K GNU extension: private key without secrete parts km.s2k.parse(bytearray(b'\xff\x00\x65\x00GNU\x01')) # wrap key material in PrivKeyV4 containing info about algo, creation timestamp, ... privkey = PrivKeyV4() privkey.pkalg = pubkey.pkalg privkey.keymaterial = km privkey.created = pubkey.created privkey.update_hlen() # wrap private key in a PGPKey object key = PGPKey() key._key = privkey return key
def test_add_subkey(self, pkspec, skspec): alg, size = skspec if not alg.can_gen: pytest.xfail('Key algorithm {} not yet supported'.format(alg.name)) if isinstance(size, EllipticCurveOID) and not size.can_gen: pytest.xfail('Curve {} not yet supported'.format(size.name)) key = self.keys[pkspec] subkey = PGPKey.new(*skspec) # before adding subkey to key, the key packet should be a PrivKeyV4, not a PrivSubKeyV4 assert isinstance(subkey._key, PrivKeyV4) assert not isinstance(subkey._key, PrivSubKeyV4) key.add_subkey(subkey, usage={KeyFlags.EncryptCommunications}) # now that we've added it, it should be a PrivSubKeyV4 assert isinstance(subkey._key, PrivSubKeyV4) # self-verify assert key.verify(subkey) sv = key.verify(key) assert sv assert subkey in sv # try to verify with GPG self.gpg_verify_key(key)
def main(): args = parseargs() # also print info messages logging.basicConfig(level=logging.INFO, format='[%(levelname)s] %(message)s') # extract key material from firmware firmware = Firmware(args.fw, args.udid) # bruteforce firmware password if necessary if firmware.locked: if not args.dict: logging.critical("Firmware is password protected: please provide a dictionary with -d option") sys.exit(1) password = bruteforce(args.dict, firmware) if password is None: logging.critical("No valid password found in provided dictionary") sys.exit(1) logging.info("Firmware unlocked with password: {}".format(password)) pubkey, _ = PGPKey.from_file(args.key) privkey = firmware.extract_key(pubkey) if args.out == '-': # export ASCII armored version if writing to stdout sys.stdout.write(str(privkey)) else: with open(args.out, 'wb') as f: # export binary version when writing to file f.write(bytes(privkey))
def test_add_uid(self): key = PGPKey.new(pgpy.constants.PubKeyAlgorithm.RSAEncryptOrSign, 1024) add_uid(key, PGPUID.new("Name"), primary=True) self.assertEqual(len(key.userids), 1) self.assertIsNotNone(key.get_uid("Name")) self.assertTrue(key.get_uid("Name").is_primary) new_uid: PGPUID = key.get_uid("Name") self.assertIsNotNone(new_uid.selfsig) self.assertEqual(new_uid.signers.pop(), key.fingerprint.keyid) self.assertTrue(key.verify(new_uid)) uid_sig: PGPSignature = new_uid.selfsig self.assertEqual(uid_sig.created, get_uniform_time_as_datetime()) self.assertListEqual(uid_sig.cipherprefs, [pgpy.constants.SymmetricKeyAlgorithm.AES256]) self.assertListEqual( uid_sig.compprefs, [pgpy.constants.CompressionAlgorithm.Uncompressed]) self.assertListEqual(uid_sig.hashprefs, [pgpy.constants.HashAlgorithm.SHA512]) add_uid(key, PGPUID.new("Secondary"), False) self.assertEqual(len(key.userids), 2) self.assertFalse(key.get_uid("Secondary").is_primary)
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 list_packets(self, keydata): # NOTE: while is known how to get the packets from PGPKey, # use gpg only here import subprocess key, _ = PGPKey.from_blob(keydata) keypath = self._save_key_to_file(key) sp = subprocess.Popen(['/usr/bin/gpg', '--list-packets', keypath], stdout=subprocess.PIPE, stderr=subprocess.PIPE) out, err = sp.communicate() if sys.version_info >= (3, 0): out = out.decode() packets = [] lines = [] last_package_type = None for rawline in out.splitlines(): line = rawline.strip() c = line[0:1] if c == "#": continue if c == ":": i = line[1:].find(c) if i != -1: ptype = line[1:i + 1] pvalue = line[i + 2:].strip() if last_package_type is not None: packets.append(last_package_type + (lines, )) lines = [] last_package_type = (ptype, pvalue) else: assert last_package_type, line lines.append(line) else: packets.append(last_package_type + (lines, )) return packets
def test_verify_subkey_revocation_signature(): keyblob = ('-----BEGIN PGP PUBLIC KEY BLOCK-----\n' '\n' 'mI0EWgtKbAEEAOEjq2UsapzI996tHhvGB7mJTo1sneUso20vz5VluECI0Xv0nr0j\n' 'BfknMFNeuPRR5sopgnrYT2ezJxp60D1NFaKgDh0z0qv9spk9FTP4YtaE5pfZRk3l\n' 'iGgyY7WiJBhKLb7ne3PeG8mtju4T+9ejbN4hVx1Vz9WHKkLGeBGkOcYZABEBAAG0\n' 'HVRlc3QgUmV2b2NhdGlvbiA8YWJjQGRlZi5naGk+iM4EEwEIADgWIQRIuXHQYB9/\n' 'm0hHY/8zq5Y87Iwq4QUCWgtKbAIbAwULCQgHAgYVCAkKCwIEFgIDAQIeAQIXgAAK\n' 'CRAzq5Y87Iwq4RKuA/46Zg3OSmRPJJNQegoDGLGwj81sgrLFPVDV2dSAxYPiGH3j\n' 'JNM760NS51FLHQvxwa9XV9/4xzL9jqsV8vD+lX5aphZS6h2olPAy9CP2FK8KFrv1\n' 'Rap2y9D68LStDv2jFyEYEGCCvon3Ff6O2PxwG98xkaskBPH6knGjK6rrMvYI/7iN\n' 'BFoLSmwBBACbGvXVtDH4aTJ3UbN/3UnLKb05ogmZDpkx8A2qGnUu1QvIxqi56emU\n' 'TfbxKv8jne0qas0IJ1OWrcTAuPvwgH4TJERAkngxzdYXR6ZHEO3/L8s0XSLobW5E\n' 'nsGnFw/PG5Lrxv1YA7nBlCKennrlaU9iiUguOUK7SW7To1SOojTOcQARAQABiLYE\n' 'KAEIACAWIQRIuXHQYB9/m0hHY/8zq5Y87Iwq4QUCWgtKuAIdAwAKCRAzq5Y87Iwq\n' '4eFnA/4oOnM7kjgIYqs2TgAxuddMabx1US9yYZDG097Nxfw1DFJoFOg4ozrrWNRz\n' 'F3AHo7Ocue288VYIJtjH4KB2vGAYdWq8j6bywW7t4Be2WsU4MCJqETxS+3Gv65B6\n' 'NBq4Y8lJvKO/cwsqYI6XWsJsmnVns0XOdv/k6ZouVdpUu5Fpr4i2BBgBCAAgFiEE\n' 'SLlx0GAff5tIR2P/M6uWPOyMKuEFAloLSmwCGwwACgkQM6uWPOyMKuFrOAP/ZemA\n' 'yfU6zSfiReQ5fsiQhiy2jZx+JVweZ0ESgDuIvT4tlB4WK87OcITd40rTalGezRuE\n' 'fhi3IcnDc7L+kBGNhP3IY8IFVNYGqfowIYLl/RX+3BUjuaDpunO9kIBrhm0WrC6Y\n' '+padVqwTFNFteQR0N9BW1qNf7HB20BCaElxGCuI=\n' '=EoFv\n' '-----END PGP PUBLIC KEY BLOCK-----\n') pubkey, _ = PGPKey.from_blob(keyblob) subkey = pubkey.subkeys['8ABD4FB3046BBCF8'] revsig = subkey._signatures[1] assert pubkey.verify(subkey, revsig)
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_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_key_deprecated_rsa_alg(self, key_alg_rsa_depr, recwarn): k = PGPKey.new(key_alg_rsa_depr, 512) w = recwarn.pop() assert str(w.message) == '{:s} is deprecated - generating key using RSAEncryptOrSign'.format(key_alg_rsa_depr.name) # assert w.filename == __file__ assert k.key_algorithm == PubKeyAlgorithm.RSAEncryptOrSign
def _verify_legal_key_with_single_userid(key: PGPKey, single_uid_expected: bool = True ) -> bool: if single_uid_expected: if not len(key.userids) == 1: # more than just one user id included return False single_uid: PGPUID = key.userids[0] if not single_uid.is_uid: # photo uids are not supported return False verification_result = key.verify(single_uid) if not verification_result: # no valid self-signature on this key return False else: if len(key.userids) != 0: # did not expect a userid return False if not KeyStore._verify_no_subkeys_signers_revsigs(key): return False return True
def test_add_subkey(self, pkspec, skspec): if pkspec not in self.keys: pytest.skip('Keyspec {} not in keys; must not have generated'.format(pkspec)) alg, size = skspec if not alg.can_gen: pytest.xfail('Key algorithm {} not yet supported'.format(alg.name)) if isinstance(size, EllipticCurveOID) and ((not size.can_gen) or size.name not in _openssl_get_supported_curves()): pytest.xfail('Curve {} not yet supported'.format(size.name)) key = self.keys[pkspec] subkey = PGPKey.new(*skspec) # before adding subkey to key, the key packet should be a PrivKeyV4, not a PrivSubKeyV4 assert isinstance(subkey._key, PrivKeyV4) assert not isinstance(subkey._key, PrivSubKeyV4) key.add_subkey(subkey, usage={KeyFlags.EncryptCommunications}) # now that we've added it, it should be a PrivSubKeyV4 assert isinstance(subkey._key, PrivSubKeyV4) # self-verify assert key.verify(subkey) sv = key.verify(key) assert sv assert subkey in sv # try to verify with GPG self.gpg_verify_key(key)
def sign_security_txt(data: str) -> Dict[str, str]: """ Sign security.txt. :param data: data to sign :type data: str :return: templatetag context data :rtype: Dict[str, str] :raises ImproperlyConfigured: in case of bad signing config """ if (settings.SECURITY_TXT_SIGN and not settings.SECURITY_TXT_SIGNING_KEY ) or ( # type: ignore # noqa: E501 not Path(settings.SECURITY_TXT_SIGNING_KEY).exists( ) # type: ignore # noqa: E501 ): raise ImproperlyConfigured key, _ = PGPKey.from_file(filename=settings.SECURITY_TXT_SIGNING_KEY ) # type: ignore # noqa: E501 return { "DATA": data, "SIGNATURE": key.sign(subject=data), }
def generate_pgp_key(name, email, comment, passphrase=None, armor=True): # We need to specify all of our preferences because PGPy doesn't have any built-in key preference defaults at this time. # This example is similar to GnuPG 2.1.x defaults, with no expiration or preferred keyserver key = PGPKey.new(PubKeyAlgorithm.RSAEncryptOrSign, 4096) uid = PGPUID.new(name, email=email, comment=comment) key.add_uid(uid, usage={ KeyFlags.Sign, KeyFlags.EncryptCommunications, KeyFlags.EncryptStorage }, hashes=[ HashAlgorithm.SHA256, HashAlgorithm.SHA384, HashAlgorithm.SHA512, HashAlgorithm.SHA224 ], ciphers=[ SymmetricKeyAlgorithm.AES256, SymmetricKeyAlgorithm.AES192, SymmetricKeyAlgorithm.AES128 ], compression=[ CompressionAlgorithm.ZLIB, CompressionAlgorithm.BZ2, CompressionAlgorithm.ZIP, CompressionAlgorithm.Uncompressed ]) # Protecting the key if passphrase: key.protect(passphrase, SymmetricKeyAlgorithm.AES256, HashAlgorithm.SHA256) else: print('WARNING: Unprotected key', file=sys.stderr) pub_data = str(key.pubkey) if armor else bytes( key.pubkey) # armored or not sec_data = str(key) if armor else bytes(key) # armored or not return (pub_data, sec_data)
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_load_from_bytearray(self, gpg_keyid_file): tkb = bytearray(os.stat(self.kf).st_size) with open(self.kf, 'rb') as tkf: tkf.readinto(tkb) key, _ = PGPKey.from_blob(tkb) assert key.fingerprint.keyid in gpg_keyid_file(self.kf.replace('tests/testdata/', ''))
def get_keys(self) -> list: session = self.get_session() keys = session.query(Key).all() deserialized_keys = [] for key in keys: deserialized_key, other = PGPKey.from_blob(key.key) deserialized_keys.append(deserialized_key) return deserialized_keys
def test_load_from_bytearray(self, kf): tkb = bytearray(os.stat(kf).st_size) with open(kf, 'rb') as tkf: tkf.readinto(tkb) key, _ = PGPKey.from_blob(tkb) assert key.fingerprint == _fingerprints[os.path.basename(kf)]
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 _get_public_key(self, email): email = utils.str(email) r = yield self.api.keys('?Email={}'.format(email), blocking=False, response=responses.KeysResponse) self.PublicKeys[email] = [ PGPKey.from_blob(k.PublicKey)[0] for k in r.Keys ] return_value(r)
def test_verify_wrongkey(self, rsa_pub): wrongkey, _ = PGPKey.from_file( 'tests/testdata/signatures/aptapproval-test.key.asc') sig = PGPSignature.from_file( 'tests/testdata/signatures/debian-sid.sig.asc') with pytest.raises(PGPError): wrongkey.verify(_read('tests/testdata/signatures/debian-sid.subj'), sig)
def test_verify_invalid_sig(self, string, key_alg): # generate a keypair u = PGPUID.new('asdf') k = PGPKey.new(key_alg, key_alg_size[key_alg]) k.add_uid(u, usage={KeyFlags.Certify, KeyFlags.Sign}, hashes=[HashAlgorithm.SHA1]) # sign string with extra characters (this means k.pubkey.verify(string) will return false sig = k.sign(string + 'asdf') assert not k.pubkey.verify(string, sig)
def test_new_key(self, key_alg): # create a key and a user id and add the UID to the key uid = PGPUID.new('Hugo Gernsback', 'Science Fiction Plus', '*****@*****.**') key = PGPKey.new(key_alg, key_alg_size[key_alg]) key.add_uid(uid, hashes=[HashAlgorithm.SHA224]) # self-verify the key assert key.verify(key) self.gen_keys[key_alg] = key
def abe(): uid = PGPUID.new('Abraham Lincoln', comment='Honest Abe', email='*****@*****.**') with open('tests/testdata/abe.jpg', 'rb') as abef: abebytes = bytearray(os.fstat(abef.fileno()).st_size) abef.readinto(abebytes) uphoto = PGPUID.new(abebytes) # Abe is pretty oldschool, so he uses a DSA primary key # normally he uses an ElGamal subkey for encryption, but PGPy doesn't support that yet, so he's settled for RSA for now key = PGPKey.new(PubKeyAlgorithm.DSA, 1024) subkey = PGPKey.new(PubKeyAlgorithm.RSAEncryptOrSign, 1024) key.add_uid(uid, usage={KeyFlags.Certify, KeyFlags.Sign}, hashes=[HashAlgorithm.SHA224, HashAlgorithm.SHA1], ciphers=[SymmetricKeyAlgorithm.AES128, SymmetricKeyAlgorithm.Camellia128, SymmetricKeyAlgorithm.CAST5], compression=[CompressionAlgorithm.ZLIB]) key.add_uid(uphoto) key.add_subkey(subkey, usage={KeyFlags.EncryptCommunications, KeyFlags.EncryptStorage}) return key
def test_verify_invalid_sig(self, pkspec, string): # test verifying an invalid signature u = PGPUID.new('asdf') k = PGPKey.new(*pkspec) k.add_uid(u, usage={KeyFlags.Certify, KeyFlags.Sign}, hashes=[HashAlgorithm.SHA1]) # sign the string with extra characters, so that verifying just string fails sig = k.sign(string + 'asdf') sv = k.pubkey.verify(string, sig) assert not sv assert sig in sv
def test_sign_encrypted_message(self, sf, cipher): # test decrypting a message sec, _ = PGPKey.from_file(sf) if (sec.fingerprint, cipher) not in self.msgs: pytest.skip('Message not present; see test_encrypt_message skip or xfail reason') emsg = self.msgs[(sec.fingerprint, cipher)] emsg |= sec.sign(emsg) assert emsg.is_signed assert emsg.is_encrypted assert isinstance(next(iter(emsg)), PGPSignature)
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_decrypt_message(self, sf, cipher): # test decrypting a message sec, _ = PGPKey.from_file(sf) if (sec.fingerprint, cipher) not in self.msgs: pytest.skip('Message not present; see test_encrypt_message skip or xfail reason') emsg = self.msgs[(sec.fingerprint, cipher)] dmsg = sec.decrypt(emsg) assert dmsg.message == "This message will have been encrypted" # now check with GnuPG, if possible if gpg_ver < '2.1' and sec.key_algorithm in {PubKeyAlgorithm.ECDSA, PubKeyAlgorithm.ECDH}: # GnuPG prior to 2.1.x does not support EC* keys, so skip this step return assert self.gpg_decrypt(emsg, sec).decode('utf-8') == dmsg.message
def test_new_subkey(self, key_alg): key = self.gen_keys[key_alg] subkey = PGPKey.new(subkey_alg[key_alg], key_alg_size[subkey_alg[key_alg]]) assert subkey._key assert not isinstance(subkey._key, PrivSubKeyV4) # now add the subkey to key and then verify it key.add_subkey(subkey, usage={KeyFlags.EncryptCommunications}) # subkey should be a PrivSubKeyV4 now, not a PrivKeyV4 assert isinstance(subkey._key, PrivSubKeyV4) # self-verify sv = self.gen_keys[key_alg].verify(self.gen_keys[key_alg]) assert sv assert subkey in sv
def test_gen_key(self, alg, size): # create a primary key with a UID uid = PGPUID.new('Test Key', '{}.{}'.format(alg.name, size), '*****@*****.**') key = PGPKey.new(alg, size) if alg is PubKeyAlgorithm.ECDSA: # ECDSA keys require larger hash digests key.add_uid(uid, hashes=[HashAlgorithm.SHA384]) else: key.add_uid(uid, hashes=[HashAlgorithm.SHA224]) assert uid in key # self-verify the key assert key.verify(key) self.keys[(alg, size)] = key # try to verify with GPG self.gpg_verify_key(key)
def test_new_key_invalid_size(self, badkey): key_alg, key_size = badkey with pytest.raises(ValueError): PGPKey.new(key_alg, key_size)
def rsa_enc(): return PGPKey.from_file('tests/testdata/keys/rsa.1.enc.asc')[0]
def targette_sec(): return PGPKey.from_file('tests/testdata/keys/targette.sec.rsa.asc')[0]
def targette_pub(): return PGPKey.from_file('tests/testdata/keys/targette.pub.rsa.asc')[0]
def temp_subkey(): return PGPKey.new(PubKeyAlgorithm.RSAEncryptOrSign, 512)
def test_new_key_no_uid_action(self): key = PGPKey.new(PubKeyAlgorithm.RSAEncryptOrSign, 1024) with pytest.raises(PGPError): key.sign('asdf')
def test_load_from_file(self, kf): key, _ = PGPKey.from_file(kf) assert key.fingerprint == _fingerprints[os.path.basename(kf)]
def test_load_from_bytes(self, kf): with open(kf, 'rb') as tkf: key, _ = PGPKey.from_blob(tkf.read()) assert key.fingerprint == _fingerprints[os.path.basename(kf)]
def test_new_key_unimplemented_alg(self, key_alg_unim): with pytest.raises(NotImplementedError): PGPKey.new(key_alg_unim, 512)
def rsa_pub(): return PGPKey.from_file('tests/testdata/keys/rsa.1.pub.asc')[0]
key.add_uid(uphoto) key.add_subkey(subkey, usage={KeyFlags.EncryptCommunications, KeyFlags.EncryptStorage}) return key @pytest.fixture(scope='module') def targette_pub(): return PGPKey.from_file('tests/testdata/keys/targette.pub.rsa.asc')[0] @pytest.fixture(scope='module') def targette_sec(): return PGPKey.from_file('tests/testdata/keys/targette.sec.rsa.asc')[0] seckeys = [ PGPKey.from_file(f)[0] for f in sorted(glob.glob('tests/testdata/keys/*.sec.asc')) ] pubkeys = [ PGPKey.from_file(f)[0] for f in sorted(glob.glob('tests/testdata/keys/*.pub.asc')) ] class TestPGPKey_Actions(object): sigs = {} msgs = {} def gpg_verify(self, subject, sig=None, pubkey=None): # verify with GnuPG with gpg.Context(armor=True, offline=True) as c: c.set_engine_info(gpg.constants.PROTOCOL_OpenPGP, home_dir=gnupghome) # do we need to import the key? if pubkey: try:
def test_empty_key_action(self): key = PGPKey() with pytest.raises(PGPError): key.sign('asdf')