def clean(self) -> bool: """ Validate the PGP key and update relevant attributes. In key-cert objects, the method, owner and fingerpr objects should be auto-generated based on the certif object. The certif object should be a valid PGP key, matching the ID in the primary key. Note that the PGP key is imported into the keyring every time this is called - this is intentional, to decouple the RPSL database state from the gpg keyring state. """ if not super().clean(): return False # pragma: no cover gpg = get_gpg_instance() certif_data = '\n'.join(self.parsed_data.get('certif', [])).replace(',', '\n') result = gpg.import_keys(certif_data) if len(result.fingerprints) != 1: msg = f'Unable to read public PGP key: key corrupt or multiple keys provided' if result.results: msg = f'{msg}: {result.results[0]["text"]}' self.messages.error(msg) return False self.fingerprint = result.fingerprints[0] expected_object_name = 'PGPKEY-' + self.fingerprint[-8:] actual_object_name = self.parsed_data['key-cert'].upper() fingerprint_formatted = self.format_fingerprint(self.fingerprint) if expected_object_name != actual_object_name: self.messages.error( f'Invalid object name {actual_object_name}: does not match key fingerprint {fingerprint_formatted}, ' f'expected object name {expected_object_name}') return False self._update_attribute_value('fingerpr', fingerprint_formatted) self._update_attribute_value( 'owner', gpg.list_keys(keys=self.fingerprint)[0]['uids']) self._update_attribute_value('method', 'PGP') return True
def verify(self, message: str) -> bool: gpg = get_gpg_instance() result = gpg.verify(message) return result.valid and result.key_status is None and \ self.format_fingerprint(result.fingerprint) == self.parsed_data['fingerpr']