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_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_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_contains_userid(self): key, userids = self._create_test_key() self.assertTrue(contains_userid(key, userids[2])) self.assertTrue(contains_userid(key, PGPUID.new("UID 4"))) self.assertTrue(contains_userid(key, "UID 4")) self.assertFalse(contains_userid(key, PGPUID.new("Not present"))) self.assertFalse(contains_userid(key, "Not present"))
def test_may_certify(self): key, userids = self._create_test_key() self.assertTrue(may_certify(userids[2], key)) self.assertTrue(may_certify(PGPUID.new("UID 4"), key)) self.assertTrue(may_certify("UID 4", key)) self.assertFalse(may_certify(PGPUID.new("Not present"), key)) self.assertFalse(may_certify("Not present", key))
def test_uid_is_in(self): uid = "John Doe" desired_uids = ["Mister Example", uid, PGPUID.new("Jane Doe")] self.assertTrue(uid_is_in(uid, desired_uids)) self.assertTrue(uid_is_in(PGPUID.new(uid), desired_uids)) self.assertTrue(uid_is_in("Jane Doe", desired_uids)) self.assertFalse(uid_is_in("Not in there", desired_uids)) self.assertFalse(uid_is_in(uid, None)) self.assertFalse(uid_is_in(uid, []))
def test_uid_as_str(self): self.assertEqual( uid_as_str( PGPUID.new("First Middle b. Last", "Some Comment", "*****@*****.**")), "First Middle b. Last (Some Comment) <*****@*****.**>") self.assertEqual(uid_as_str(PGPUID.new("Just a Name")), "Just a Name") # noinspection PyTypeChecker self.assertRaises(TypeError, lambda: uid_as_str(None))
def test_may_certify_any(self): key, userids = self._create_test_key() self.assertTrue(may_certify_any([userids[2], "Not present"], key)) self.assertTrue(may_certify_any(["Not present", userids[2]], key)) self.assertTrue( may_certify_any(["1", "2", "3", PGPUID.new("UID 4")], key)) self.assertFalse(may_certify_any([PGPUID.new("Not present")], key)) self.assertFalse(may_certify_any(["1", "2", "3"], key)) self.assertFalse(may_certify_any([], key))
def _create_test_key() -> Tuple[PGPKey, List[PGPUID]]: userids: List[PGPUID] = [ PGPUID.new("UID 1"), PGPUID.new("UID 2"), PGPUID.new("UID 3"), PGPUID.new("UID 4") ] key = PGPKey.new(pgpy.constants.PubKeyAlgorithm.RSAEncryptOrSign, 512) for userid in userids: key.add_uid(userid, selfsign=True) return key, userids
def test_add_altuid(self, pkspec): if pkspec not in self.keys: pytest.skip('Keyspec {} not in keys; must not have generated'.format(pkspec)) key = self.keys[pkspec] uid = PGPUID.new('T. Keyerson', 'Secondary UID', '*****@*****.**') expiration = datetime.utcnow() + timedelta(days=2) # add all of the sbpackets that only work on self-certifications key.add_uid(uid, usage=[KeyFlags.Certify, KeyFlags.Sign], ciphers=[SymmetricKeyAlgorithm.AES256, SymmetricKeyAlgorithm.Camellia256], hashes=[HashAlgorithm.SHA384], compression=[CompressionAlgorithm.ZLIB], key_expiration=expiration, keyserver_flags=0x80, keyserver='about:none', primary=False) sig = uid.selfsig assert sig.type == SignatureType.Positive_Cert assert sig.cipherprefs == [SymmetricKeyAlgorithm.AES256, SymmetricKeyAlgorithm.Camellia256] assert sig.hashprefs == [HashAlgorithm.SHA384] assert sig.compprefs == [CompressionAlgorithm.ZLIB] assert sig.features == {Features.ModificationDetection} assert sig.key_expiration == expiration - key.created assert sig.keyserver == 'about:none' assert sig.keyserverprefs == [KeyServerPreferences.NoModify] assert uid.is_primary is False # try to verify with GPG self.gpg_verify_key(key)
def test_create_identity(self): _, secondary_uids = self._create_test_key() primary_uid = PGPUID.new("Primary") pub, sec = create_identity(primary_uid, secondary_uids) self.assertEqual(pub.fingerprint, sec.fingerprint) self.assertTrue(pub.is_public) self.assertFalse(sec.is_public) self.assertFalse(sec.is_protected) self.assertEqual(pub.created, get_uniform_time_as_datetime()) self.assertEqual(pub.key_algorithm, pgpy.constants.PubKeyAlgorithm.EdDSA) self.assertEqual(pub.key_size, pgpy.constants.EllipticCurveOID.Ed25519) self.assertIsNotNone(pub.get_uid(get_pseudo_uid().name)) primary_uid_from_key: PGPUID = pub.get_uid("Primary") self.assertIsNotNone(primary_uid_from_key) self.assertTrue(primary_uid_from_key.is_primary) self.assertEqual(len(pub.userids), 6) primary_uid_count = 0 for u in pub.userids: self.assertIsNotNone(u.selfsig) self.assertEqual(u.selfsig.created, get_uniform_time_as_datetime()) if u.is_primary: primary_uid_count += 1 self.assertEqual(primary_uid_count, 1)
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 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_remove_userid(self, targette_sec): # create a temporary userid, add it, and then remove it tempuid = PGPUID.new('Temporary Youx\'seur') targette_sec.add_uid(tempuid) assert tempuid in targette_sec targette_sec.del_uid('Temporary Youx\'seur') assert tempuid not in targette_sec
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 from_dict(cls, uid_dict: dict) -> 'GitAnonIdentity': name: str = uid_dict['name'] email: str = uid_dict['email'] comment: str = uid_dict['comment'] auto_reveal: bool = uid_dict['auto_reveal'] auto_reveal_encrypted: bool = uid_dict['auto_reveal_encrypted'] uid = PGPUID.new(name, email, comment) return GitAnonIdentity(uid, auto_reveal, auto_reveal_encrypted)
def _generate_key(username: str): primary_key = PGPKey.new(PubKeyAlgorithm.RSAEncryptOrSign, 4096) primary_key.add_uid( PGPUID.new(username), usage={KeyFlags.EncryptCommunications}, uidhashes=[HashAlgorithm.SHA512], ciphers=[SymmetricKeyAlgorithm.AES256], compression=[CompressionAlgorithm.ZIP] ) return primary_key
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 _gen_skey_usage_all(addr): seckey = PGPKey.new(SKEY_ALG, KEY_SIZE) # NOTE: pgpy implements separate attributes for name and e-mail # address. Name is mandatory. # Here e-mail address is used for the attribute name, # so that the uid is 'e-mail adress'. # If name attribute would be set to empty string # and email to the e-mail address, the uid would be # ' <e-mail address>', which we do not want. uid = PGPUID.new(addr) seckey.add_uid(uid, usage=SKEY_USAGE_ALL, **SKEY_ARGS) return seckey
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 generate(username: str): primary_key = PGPKey.new(PubKeyAlgorithm.RSAEncryptOrSign, 4096) primary_key.add_uid(PGPUID.new(username), usage={KeyFlags.EncryptCommunications}, uidhashes=[HashAlgorithm.SHA512], ciphers=[SymmetricKeyAlgorithm.AES256], compression=[CompressionAlgorithm.ZIP]) secho("Primary key, to be saved in server", fg=colors.BLUE) secho(primary_key.fingerprint, fg=colors.RED) secho(str(primary_key), fg=colors.YELLOW) secho("Public key, to be saved in server", fg=colors.BLUE) secho(primary_key.fingerprint, fg=colors.RED) secho(str(primary_key.pubkey), fg=colors.GREEN)
def test_sign_security_txt__render(self) -> None: """Test templatetag rendering result.""" expected = """ -----BEGIN PGP SIGNED MESSAGE----- Hash: SHA256 -----BEGIN PGP SIGNATURE----- """ template: Template = Template( "{% load security_txt_tags %}" # noqa: FS003 "{% with security_txt as DATA %}{% sign_security_txt DATA %}{% endwith %}" # noqa: FS003,E501 ) key = PGPKey.new(PubKeyAlgorithm.RSAEncryptOrSign, 4096) uid = PGPUID.new(pn="TEST", comment="Test", email="*****@*****.**") 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, ], ) Path(self.KEY_PATH).write_text(data=str(key)) result: str = template.render(context=Context()) self.assertTrue(expr=expected.strip() in result.strip())
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 generate_pgp_pair(self, comment, passphrase, armor=True, active=False): """Generate PGP key pair to be used by keyserver.""" # 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 comment = comment if comment else "Generated for use in LocalEGA." key = PGPKey.new(PubKeyAlgorithm.RSAEncryptOrSign, 4096) uid = PGPUID.new(self.name, email=self.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 key.protect(passphrase, SymmetricKeyAlgorithm.AES256, HashAlgorithm.SHA256) 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 _create_key() -> None: certifier = PGPKey.new(pgpy.constants.PubKeyAlgorithm.RSAEncryptOrSign, 512) certifier.add_uid(PGPUID.new("Can't sign without a UID-Self-Signature"), selfsign=True) key = PGPKey.new(pgpy.constants.PubKeyAlgorithm.RSAEncryptOrSign, 512) key.add_uid(PGPUID.new("First UID"), selfsign=True) key.add_uid(PGPUID.new("Second UID"), selfsign=True) key.add_uid(PGPUID.new("Duplicate UID"), selfsign=True) key.add_uid(PGPUID.new("Duplicate UID"), selfsign=True) # key.add_uid(PGPUID.new("Unsigned UID"), selfsign=False) certified_uid = PGPUID.new("Certified UID") key.add_uid(certified_uid, selfsign=True) key |= certifier.certify(key) certified_uid |= certifier.certify(key.get_uid("Certified UID")) print(certifier) print(key)
def abe(): return PGPUID.new('Abraham Lincoln', comment='Honest Abe', email='*****@*****.**')
def unce(): return PGPUID.new(six.u('Temperair\xe9e Youx\'seur'), comment=six.u('\u2603'), email='*****@*****.**')
def une(): return PGPUID.new(six.u('Temperair\xe9e Youx\'seur'), email='*****@*****.**')
def unc(): return PGPUID.new(six.u('Temperair\xe9e Youx\'seur'), comment=six.u('\u2603'))
def test_or_typeerror(self): u = PGPUID.new("Asdf Qwert") with pytest.raises(TypeError): u |= 12
def un(): return PGPUID.new(six.u('Temperair\xe9e Youx\'seur'))
def abe_image(): with open('tests/testdata/abe.jpg', 'rb') as abef: abebytes = bytearray(os.path.getsize('tests/testdata/abe.jpg')) abef.readinto(abebytes) return PGPUID.new(abebytes)
def userphoto(): with open('tests/testdata/pgp.jpg', 'rb') as pf: pbytes = bytearray(os.fstat(pf.fileno()).st_size) pf.readinto(pbytes) return PGPUID.new(pbytes)