예제 #1
0
    def _get_gpg_output_for_pubkey_file(self, pubkey_file):
        with TemporaryDirectory() as temp_gpg_home:
            gpg = GPG(gnupghome=temp_gpg_home)
            with open(pubkey_file, 'rb') as pubkey_fh:
                gpg.import_keys(pubkey_fh.read())
            gpg_stdout = check_output([
                'gpg',
                '--homedir', temp_gpg_home,
                '--keyid-format', '0xlong',
                '--with-fingerprint',
                '--list-options', 'show-uid-validity',
                '--verify-options', 'show-uid-validity',
                # '--list-sigs',
                # Public keys for signatures over the UIDs might not be present.
                '--list-public-keys'
            ]).decode('utf-8')
            truncated_lines = []
            in_header = True
            for line in gpg_stdout.split('\n'):
                # OpenPGP subkeys might be subject to more frequent change
                # and are expected to not always be updated in the keyring.
                # You might need to update OpenPGP subkeys from keyservers.
                if not in_header and not re.match(r'sub\s', line):
                    truncated_lines.append(line)

                if re.match(r'^---------', line):
                    in_header = False
            return '\n'.join(truncated_lines)
예제 #2
0
def get_expirations(keylist):
    """
    This function is not implemented in GPG object class because need to operate
    on the whole keys
    """
    atfork()

    try:
        temp_gpgroot = os.path.join(GLSetting.gpgroot, "-expiration_check-%s" % random.randint(0, 0xFFFF) )
        os.makedirs(temp_gpgroot, mode=0700)
        gpexpire= GPG(gnupghome=temp_gpgroot, options="--trust-model always")
    except Exception as excep:
        log.err("Unable to setup expiration check environment: %s" % excep)
        raise excep

    try:
        for key in keylist:
            gpexpire.import_keys(key)
    except Exception as excep:
        log.err("Error in GPG import_keys: %s" % excep)
        raise excep

    try:
        all_keys = gpexpire.list_keys()
    except Exception as excep:
        log.err("Error in GPG list_keys: %s" % excep)
        raise excep

    expirations = {}
    for ak in all_keys:
        expirations.update({ ak['fingerprint'] : ak['date']})

    return expirations
예제 #3
0
    def _get_gpg_output_for_pubkey_file(self, pubkey_file):
        with TemporaryDirectory() as temp_gpg_home:
            gpg = GPG(gnupghome=temp_gpg_home)
            with open(pubkey_file, 'rb') as pubkey_fh:
                gpg.import_keys(pubkey_fh.read())
            gpg_stdout = check_output([
                'gpg',
                '--homedir',
                temp_gpg_home,
                '--keyid-format',
                '0xlong',
                '--with-fingerprint',
                '--list-options',
                'show-uid-validity',
                '--verify-options',
                'show-uid-validity',
                # '--list-sigs',
                # Public keys for signatures over the UIDs might not be present.
                '--list-public-keys'
            ]).decode('utf-8')
            truncated_lines = []
            in_header = True
            for line in gpg_stdout.split('\n'):
                # OpenPGP subkeys might be subject to more frequent change
                # and are expected to not always be updated in the keyring.
                # You might need to update OpenPGP subkeys from keyservers.
                if not in_header and not re.match(r'sub\s', line):
                    truncated_lines.append(line)

                if re.match(r'^---------', line):
                    in_header = False
            return '\n'.join(truncated_lines)
예제 #4
0
def gpg_init(tmpdir, benchmark, openpgp_keys, monkeypatch, _):
    pubkey = openpgp_keys[0]
    privkey = openpgp_keys[2]  # this is PRIVATE_KEY
    gpg = GPG(homedir=tmpdir.dirname)
    gpg.import_keys(pubkey.key_data)
    gpg.import_keys(privkey.key_data)
    return gpg, pubkey, privkey
예제 #5
0
def get_expirations(keylist):
    """
    This function is not implemented in GPG object class because need to operate
    on the whole keys
    """
    try:
        temp_gpgroot = os.path.join(
            GLSetting.gpgroot,
            "-expiration_check-%s" % xeger(r'[A-Za-z0-9]{8}'))
        os.makedirs(temp_gpgroot, mode=0700)
        gpexpire = GPG(gnupghome=temp_gpgroot,
                       options=['--trust-model', 'always'])
    except Exception as excep:
        log.err("Unable to setup expiration check environment: %s" % excep)
        raise excep

    try:
        for key in keylist:
            gpexpire.import_keys(key)
    except Exception as excep:
        log.err("Error in GPG import_keys: %s" % excep)
        raise excep

    try:
        all_keys = gpexpire.list_keys()
    except Exception as excep:
        log.err("Error in GPG list_keys: %s" % excep)
        raise excep

    expirations = {}
    for ak in all_keys:
        expirations.update({ak['fingerprint']: ak['date']})

    return expirations
예제 #6
0
    def _encrypt(self, plain):
        # test if we have public keys for all recipients
        available_recipients = []
        keys = []
        for key in Key.objects.all():
            keys.append(key)
            available_recipients.extend(key.addresses.split(', '))
        logger.debug("available_recipients: %s", available_recipients)
        if not all(recipient in available_recipients
                   for recipient in self.recipients()):
            logger.error(
                "Public key not present for at least one of these recipients: %s",
                self.recipients())
            raise GPGException(
                "Public key not present for at least one recipient")

        # encryption
        with TemporaryDirectory() as temp_dir:
            gpg = GPG(gnupghome=temp_dir)
            for key in keys:
                gpg.import_keys(key.key)

            res = gpg.encrypt(plain, self.recipients(), always_trust=True)
            if not res:
                handle_gpg_error(res, 'encryption')
            return smart_text(res)
예제 #7
0
def encrypt_file(gpg: gnupg.GPG,
                 targer_folder: str):
    configuration_kwargs = utils.get_configuratation(
        path=os.path.join(
            targer_folder,
            'configuration'
        )
    )
    value = _get_decryption(configuration_kwargs=configuration_kwargs)

    gpg.import_keys(value)
    keys = gpg.list_keys()

    gpg.trust_keys(
        keys.fingerprints,
        'TRUST_ULTIMATE'
    )

    decrypted_filepaths = utils.get_files(
        path=os.path.join(
            targer_folder,
            'decrypted_files'
        )
    )

    encrypted_path = os.path.join(
        targer_folder,
        'encrypted_files'
    )

    for decryped_file in decrypted_filepaths:
        base_name = __set_file_name(path=decryped_file)

        logger.info(f'encrypting file {base_name}')

        output_file = os.path.join(
            encrypted_path,
            base_name
        )

        with open(decryped_file, 'rb') as connection:
            status = gpg.encrypt_file(
                file=connection,
                recipients=keys.fingerprints,
                output=output_file,
            )

            logger.info(f'encrypting done')

        if not status.ok:
            logger.info(f'{status.stderr}')
        else:
            logger.info(f'Status [{status.status}]')
예제 #8
0
def verify_gpg(datafile, signature_file=None) -> bool:
    """
    verify Julia releases using GPG
    """
    if signature_file is None:
        signature_file = datafile + ".asc"

    with open(GPG_PUBLIC_KEY_PATH) as fh:
        keycontent = fh.read()
    with TemporaryDirectory() as tmpdir:
        gpg = GPG(gnupghome=tmpdir)
        gpg.import_keys(keycontent)
        return bool(_verify_gpg(gpg, datafile, signature_file))
예제 #9
0
    def _sign(self, data, digest_algo):
        gpg = GPG(homedir=settings.GPG_SIGN_DIR)
        if not gpg.list_keys():
            # Import key if no private key key in keyring
            with open(settings.GPG_SIGN_KEY, 'r') as f:
                key = f.read()
            gpg.import_keys(key)

        signature = gpg.sign(data,
                             passphrase=settings.GPG_SIGN_KEY_PASSPHRASE,
                             clearsign=False,
                             detach=True,
                             digest_algo=digest_algo)

        return str(signature)
예제 #10
0
파일: repo.py 프로젝트: fonsp/TagBot
 def configure_gpg(self, key: str, password: Optional[str]) -> None:
     """Configure the repo to sign tags with GPG."""
     home = os.environ["GNUPGHOME"] = mkdtemp(prefix="tagbot_gpg_")
     os.chmod(home, S_IREAD | S_IWRITE | S_IEXEC)
     logger.debug(f"Set GNUPGHOME to {home}")
     gpg = GPG(gnupghome=home, use_agent=True)
     import_result = gpg.import_keys(self._maybe_decode_private_key(key),
                                     passphrase=password)
     if import_result.sec_imported != 1:
         logger.warning(import_result.stderr)
         raise Abort("Importing key failed")
     key_id = import_result.fingerprints[0]
     logger.debug(f"GPG key ID: {key_id}")
     if password:
         # Sign some dummy data to put our password into the GPG agent,
         # so that we don't need to supply the password when we create a tag.
         sign_result = gpg.sign("test", passphrase=password)
         if sign_result.status != "signature created":
             logger.warning(sign_result.stderr)
             raise Abort("Testing GPG key failed")
     # On Debian, the Git version is too old to recognize tag.gpgSign,
     # so the tag command will need to use --sign.
     self._git._gpgsign = True
     self._git.config("tag.gpgSign", "true")
     self._git.config("user.signingKey", key_id)
예제 #11
0
 def send_mail(self, subject, body):
     if self.gpg_key:
         with TemporaryDirectory() as tmp_dir:
             gpg = GPG(homedir=tmp_dir)
             key = gpg.import_keys(self.gpg_key)
             body = str(gpg.encrypt(body, *key.fingerprints))
     send_mail(subject, body, settings.EMAIL_ADDRESS, [self.email])
    def clean_key(self):
        """
        Raises ValidationError if the entered key is invalid or includes a GPG private key.
        """
        data = self.cleaned_data['key']
        with TemporaryDirectory() as temp_dir:
            gpg_keychain = GPG(gnupghome=temp_dir)
            res = gpg_keychain.import_keys(data)
            if not res:
                errors = [
                    forms.ValidationError(_("Invalid key."), code='invalid')
                ]
                for attr in ['status',
                             'stderr']:  # not all fields are always present
                    if hasattr(res, attr):
                        errors.append(
                            forms.ValidationError("%(name)s: %(value)s",
                                                  params={
                                                      'name': attr,
                                                      'value':
                                                      getattr(res, attr)
                                                  },
                                                  code=attr))
                raise forms.ValidationError(errors)

            if len(gpg_keychain.list_keys(
                    True)) > 0:  # check existance of private keys
                raise forms.ValidationError(_(
                    "Import public keys only, no private keys! "
                    "You should consider the private key(s) compromised."),
                                            code='private_key')
        return data
예제 #13
0
    def check_git_commits(self, repo_path='.'):
        with TemporaryDirectory() as temp_gpg_home:
            gpg = GPG(gnupghome=temp_gpg_home)

            for long_key_id in os.listdir(self._keyring_name):
                with open(os.path.join(self._keyring_name, long_key_id),
                          'rb') as pubkey_fh:
                    gpg.import_keys(pubkey_fh.read())

            repo = git.Git(repo_path)
            repo.update_environment(GNUPGHOME=temp_gpg_home)
            commit_count = 0
            # %G?: show "G" for a Good signature,
            #           "B" for a Bad signature,
            #           "U" for a good, untrusted signature and
            #           "N" for no signature
            # TODO 'N' is also returned for signatures made by expired subkeys.
            # Seems to be a bug.
            # Current workaround is only to check the HEAD commit.
            for log_line in [repo.log('--format=%H %G?').split('\n')[0]]:
                (commit_hash, signature_check) = log_line.split(' ')
                commit_count += 1
                if signature_check not in ['U', 'G']:
                    raise Exception(
                        "OpenPGP signature of commit could not be verified."
                        "\nAffected commit:\n{}".format(
                            repo.log('-1', commit_hash), ))
            logging.info(
                textwrap.dedent("""
                    OK - All commits in the repository '{repo_path}' are signed
                    and all public keys to verify the signatures are contained
                    in current HEAD of this repository.
                    """).lstrip().replace('\n',
                                          ' ').format(repo_path=repo_path, ))
            if commit_count <= 0:
                # That condition is expected to never be True because of
                # "returned with exit code 128" for "fatal: bad default revision 'HEAD'".
                # Leaving it in just to be sure (in case git becomes more
                # "friendly" in the future.
                raise Exception("Expected at least one git commit."
                                " Found {} commits.".format(commit_count, ))
            else:
                logging.info(
                    "OK - The repository '{repo_path}' contains at least one commit."
                    .format(repo_path=repo_path, ))

        return True
 def test_addresses_for_key(self):
     """Test email address extraction from GPG public keys."""
     with TemporaryDirectory() as temp_dir:
         gpg_keychain = GPG(gnupghome=temp_dir)
         res = gpg_keychain.import_keys(self.key.key)
         self.assertTrue(res)
         self.assertEqual(len(res.results), 1)
         self.assertEqual(addresses_for_key(gpg_keychain, res.results[0]), ['*****@*****.**'])
예제 #15
0
파일: pgp.py 프로젝트: zssstc/binwalk
    def _pgp_decrypt(self, encrypted_firmware, key):
        '''
        This does the actual decryption.
        '''
        try:
            tmp_dir = tempfile.mkdtemp()
            gpg = GPG(gnupghome=tmp_dir)
            gpg.import_keys(key)
            decrypted_data = gpg.decrypt(encrypted_firmware)
        finally:
            try:
                shutil.rmtree(tmp_dir)
            except OSError as exc:
                if exc.errno != errno.ENOENT:
                    raise

        return bytes(decrypted_data.data)
예제 #16
0
def gnupg_key_fingerprint(gnupg_instance: GPG, private_gpg_key: str):
    keys_imported = gnupg_instance.import_keys(private_gpg_key)
    key_fingerprint = keys_imported.fingerprints[0]
    yield key_fingerprint

    if key_fingerprint in gnupg_instance.list_keys(secret=True).fingerprints:
        remove_gpg_key_pair(gpg_binary=gnupg_instance.gpgbinary,
                            fingerprint=key_fingerprint)
예제 #17
0
 def test_addresses_for_key(self):
     """Test email address extraction from GPG public keys."""
     with TemporaryDirectory() as temp_dir:
         gpg_keychain = GPG(gnupghome=temp_dir)
         res = gpg_keychain.import_keys(self.key.key)
         self.assertTrue(res)
         self.assertEqual(len(res.results), 1)
         self.assertEqual(addresses_for_key(gpg_keychain, res.results[0]),
                          ['*****@*****.**'])
예제 #18
0
파일: forms.py 프로젝트: lugnitdgp/avskr2.0
 def clean_key(self):
     """
     Validate the key contains an email address.
     """
     key = self.cleaned_data["key"]
     gpg = GPG(gnupghome=GNUPG_HOME)
     result = gpg.import_keys(key)
     if result.count == 0:
         raise forms.ValidationError(_("Invalid Key"))
     return key
def forward_change(apps, schema_editor):
    Key = apps.get_model('email_extras', 'Key')
    Address = apps.get_model('email_extras', 'Address')

    for key in Key.objects.all():
        addresses = Address.objects.filter(address__in=key.addresses.split(','))
        addresses.update(key=key)

        gpg = GPG(gnupghome=GNUPG_HOME)
        result = gpg.import_keys(key.key)
        key.fingerprint = result.fingerprints[0]
        key.save()
예제 #20
0
 def save(self, *args, **kwargs):
     super(Key, self).save(*args, **kwargs)
     gpg = GPG(gnupghome=GNUPG_HOME)
     result = gpg.import_keys(self.key)
     addresses = []
     for key in result.results:
         addresses.extend(addresses_for_key(gpg, key))
     self.addresses = ",".join(addresses)
     for address in addresses:
         address, _ = Address.objects.get_or_create(address=address)
         address.use_asc = self.use_asc
         address.save()
예제 #21
0
 def save(self, *args, **kwargs):
     super(Key, self).save(*args, **kwargs)
     gpg = GPG(gnupghome=GNUPG_HOME)
     result = gpg.import_keys(self.key)
     addresses = []
     for key in result.results:
         addresses.extend(addresses_for_key(gpg, key))
     self.addresses = ",".join(addresses)
     for address in addresses:
         address, _ = Address.objects.get_or_create(address=address)
         address.use_asc = self.use_asc
         address.save()
예제 #22
0
def forward_change(apps, schema_editor):
    Key = apps.get_model('email_extras', 'Key')
    Address = apps.get_model('email_extras', 'Address')

    for key in Key.objects.all():
        addresses = Address.objects.filter(
            address__in=key.addresses.split(','))
        addresses.update(key=key)

        gpg = GPG(gnupghome=GNUPG_HOME)
        result = gpg.import_keys(key.key)
        key.fingerprint = result.fingerprints[0]
        key.save()
예제 #23
0
def _get_decryption(gpg: gnupg.GPG, configuration_kwargs: Dict) -> gnupg.GPG:
    ssm_name = '{environment}.{name}-{company_name}'.format(
        environment=settings.ENVIRONMENT,
        name=configuration_kwargs.get('secret_name'),
        company_name=configuration_kwargs.get('company_name'))
    secret_key = []
    for key in ['public', 'private']:
        logger.info(f'Handling {key} for decryption')

        ssm_name_extended = f'{ssm_name}-{key}'
        value = parameter_store.get_keys(profile_name='ssm',
                                         name=ssm_name_extended)

        secret_key.append(value)

    secret_keys = ''.join(secret_key)
    gpg.import_keys(secret_keys)
    keys = gpg.list_keys(True)

    gpg.trust_keys(keys.fingerprints, 'TRUST_ULTIMATE')

    return gpg
    def _encrypt(self, plain):
        # test if we have public keys for all recipients
        available_recipients = []
        keys = []
        for key in Key.objects.all():
            keys.append(key)
            available_recipients.extend(key.addresses.split(', '))
        logger.debug("available_recipients: %s", available_recipients)
        if not all(recipient in available_recipients for recipient in self.recipients()):
            logger.error("Public key not present for at least one of these recipients: %s", self.recipients())
            raise GPGException("Public key not present for at least one recipient")

        # encryption
        with TemporaryDirectory() as temp_dir:
            gpg = GPG(gnupghome=temp_dir)
            for key in keys:
                gpg.import_keys(key.key)

            res = gpg.encrypt(plain, self.recipients(), always_trust=True)
            if not res:
                handle_gpg_error(res, 'encryption')
            return smart_text(res)
예제 #25
0
def verify_gpg(datafile, signature_file=None) -> bool:
    """
    verify Julia releases using GPG
    """
    if signature_file is None:
        signature_file = datafile + ".asc"

    with open(GPG_PUBLIC_KEY_PATH) as fh:
        keycontent = fh.read()

    rst = False
    try:
        with TemporaryDirectory() as tmpdir:
            gpg = GPG(gnupghome=tmpdir)
            gpg.import_keys(keycontent)
            rst = bool(_verify_gpg(gpg, datafile, signature_file))
    except FileNotFoundError:
        # issue #45 -- might reaches here during the temp dir cleanup
        # This might only related to VM environment
        # https://bugs.python.org/issue25717
        pass
    finally:
        return rst
예제 #26
0
def import_key(keypath, keyring):
    """ Imports all keys from specified directory
    This function is idempotent, so importing the same key multiple times will
    always succeed.
    :param keypath:     path to armored key file
    :param keyring:     directory of the keyring
    """
    gpg = GPG(gnupghome=keyring)
    try:
        with open(keypath, 'r') as keyfile:
            result = gpg.import_keys(keyfile.read())
    except OSError:
        raise KeyImportError("Could not open '%s'" % keypath, keypath)
    if result.count == 0:
        raise KeyImportError("Could not import '%s'" % keypath, keypath)
예제 #27
0
 def save(self, *args, **kwargs):
     with TemporaryDirectory() as temp_dir:
         gpg_keychain = GPG(gnupghome=temp_dir)
         res = gpg_keychain.import_keys(self.key)
         if not res:
             handle_gpg_error(res, 'import')
         if len(gpg_keychain.list_keys(True)) > 0:
             raise GPGException("Will not import GPG private key!")
         addresses = []
         for key in res.results:
             addresses.extend(addresses_for_key(gpg_keychain, key))
         self.addresses = ', '.join(addresses)
     operation = "Updating" if self.pk else "Creating"
     logger.info("%s GPG key for: %s", operation, self.addresses)
     super(Key, self).save(*args, **kwargs)
예제 #28
0
def import_key(keypath, keyring):
    """ Imports all keys from specified directory
    This function is idempotent, so importing the same key multiple times will
    always succeed.
    :param keypath:     path to armored key file
    :param keyring:     directory of the keyring
    """
    gpg = GPG(gnupghome=keyring)
    try:
        with open(keypath, 'r') as keyfile:
            result = gpg.import_keys(keyfile.read())
    except OSError:
        raise KeyImportError("Could not open '%s'" % keypath, keypath)
    if result.count == 0:
        raise KeyImportError("Could not import '%s'" % keypath, keypath)
예제 #29
0
        def save_model(self, request, obj, form, change):
            """
			import the key and parse the addresses from it and save them
			and omit the super save_model call so as to never save the key instance
			"""
            gpg = GPG(gnupghome=GNUPG_HOME)
            result = gpg.import_keys(obj.key)
            if result.count == 0:
                raise forms.ValidationError("Invalid Key")
            else:
                addresses = []
                for key in result.results:
                    addresses.extend(addresses_for_key(gpg, key))
                obj.addresses = ",".join(addresses)
                for address in addresses:
                    Address.objects.get_or_create(address=address)
예제 #30
0
 def save_model(self, request, obj, form, change):
     """
     Import the key and parse the addresses from it and save
     them, and omit the super save_model call so as to never
     save the key instance.
     """
     gpg = GPG(gnupghome=GNUPG_HOME)
     result = gpg.import_keys(obj.key)
     if result.count == 0:
         raise forms.ValidationError("Invalid Key")
     else:
         addresses = []
         for key in result.results:
             addresses.extend(addresses_for_key(gpg, key))
         obj.addresses = ",".join(addresses)
         for address in addresses:
             Address.objects.get_or_create(address=address)
예제 #31
0
def key_edit(key, password, path_to_user_folder):

	try:
		gpg = GPG()
		gpg.delete_keys(key, True, passphrase=password)
		gpg.delete_keys(key)
		key_data = open(path_to_user_folder+'/main/gpg_private_key.asc').read()
		new_key = gpg.import_keys(key_data)
		new_key = new_key.results[0]['fingerprint']
		gpg.trust_keys(new_key, "TRUST_ULTIMATE")
		system('echo RELOADAGENT | gpg-connect-agent')
		copy2(path_to_user_folder+'/main/gpg_private_key.asc', path_to_user_folder+'/user_data/gpg_private_key.asc')
		return new_key

	except:
		msg = bot.send_message(message.chat.id, 'Произошла ошибка.', reply_markup = types.ReplyKeyboardRemove(selective=False))
		del_mess(msg, bot, 6)
		return key
예제 #32
0
 def configure_gpg(self, key: str, password: Optional[str]) -> None:
     """Configure the repo to sign tags with GPG."""
     home = os.environ["GNUPGHOME"] = mkdtemp(prefix="tagbot_gpg_")
     os.chmod(home, S_IREAD | S_IWRITE | S_IEXEC)
     logger.debug(f"Set GNUPGHOME to {home}")
     gpg = GPG(gnupghome=home, use_agent=True)
     # For some reason, this doesn't require the password even though the CLI does.
     import_result = gpg.import_keys(self._maybe_b64(key))
     if import_result.sec_imported != 1:
         logger.warning(import_result.stderr)
         raise Abort("Importing key failed")
     key_id = import_result.fingerprints[0]
     logger.debug(f"GPG key ID: {key_id}")
     if password:
         # Sign some dummy data to put our password into the GPG agent,
         # so that we don't need to supply the password when we create a tag.
         sign_result = gpg.sign("test", passphrase=password)
         if sign_result.status != "signature created":
             logger.warning(sign_result.stderr)
             raise Abort("Testing GPG key failed")
     self._git.config("user.signingKey", key_id)
     self._git.config("tag.gpgSign", "true")
    def clean_key(self):
        """
        Raises ValidationError if the entered key is invalid or includes a GPG private key.
        """
        data = self.cleaned_data['key']
        with TemporaryDirectory() as temp_dir:
            gpg_keychain = GPG(gnupghome=temp_dir)
            res = gpg_keychain.import_keys(data)
            if not res:
                errors = [forms.ValidationError(_("Invalid key."), code='invalid')]
                for attr in ['status', 'stderr']:  # not all fields are always present
                    if hasattr(res, attr):
                        errors.append(forms.ValidationError("%(name)s: %(value)s",
                                                            params={'name': attr, 'value': getattr(res, attr)},
                                                            code=attr))
                raise forms.ValidationError(errors)

            if len(gpg_keychain.list_keys(True)) > 0:  # check existance of private keys
                raise forms.ValidationError(_("Import public keys only, no private keys! "
                                              "You should consider the private key(s) compromised."),
                                            code='private_key')
        return data
예제 #34
0
파일: manager.py 프로젝트: grocid/Skier
def import_from_dump(file):
    """Import from an SKS dump."""
    # First, load a new GPG instance.
    gpg = GPG(gnupghome="/tmp/skier-import")

    # Read data in
    dumpf = open(file, 'rb')
    data = dumpf.read()
    dump = pgpdump.BinaryData(data)
    dumpf.close()

    # Import the keydump into gpg
    try:
        gpg.import_keys(data)
    except:
        # Yeah, whatever.
        pass
    """
    # Read in packets
    packets_flat = []
    try:
        for packet in dump.packets():
            packets_flat.append(packet)
    except Exception as e:
        # Some SKS data is malformed.
        print("SKS data in {} is malformed - truncating at packet {}".format(file, len(packets_flat)+1))

    # Unflatten list into sublists, starting at each new Publickey packet.
    packets = []
    tmpl = []
    for packet in packets_flat:
        if isinstance(packet, pgpdump.packet.PublicKeyPacket) and not isinstance(packet, pgpdump.packet.PublicSubkeyPacket) and tmpl:
            tmpl.insert(0, packet)
            gpg_output = gpg.export_keys(keyids=[packet.fingerprint.decode()])
            if gpg_output:
                tmpl.append(gpg_output)
            packets.append(tmpl)
            tmpl = []
            continue
        else:
            tmpl.append(packet)
    packets.append(tmpl)
    """
    armored = []
    for key in gpg.list_keys():
        tmpkey = gpg.export_keys(keyids=key['fingerprint'])
        if not tmpkey:
            print("{} is malformed - not importing".format(key['fingerprint']))
        armored.append(tmpkey)


    print("Importing {} keys".format(len(armored)))
    """
    for gpack in packets:
        keyinfo = KeyInfo.pgp_dump(None, packets=gpack)
        dbob = db.Key.from_keyinfo(keyinfo)
        db.db.session.add(dbob)

    db.db.session.commit()
    """

    for key in armored:
        kyinfo = KeyInfo.pgp_dump(key)
        if not kyinfo.fingerprint:
            print("Key {} is malformed - cannot be imported".format(kyinfo))
        else:
            dbob = db.Key.from_keyinfo(kyinfo)
            db.db.session.add(dbob)

    db.db.session.commit()

    shutil.rmtree("/tmp/skier-import")
예제 #35
0
class GLBPGP(object):
    """
    PGP has not a dedicated class, because one of the function is called inside a transact, and
    I'm not quite confident on creating an object that operates on the filesystem knowing
    that would be run also on the Storm cycle.
    """
    def __init__(self):
        """
        every time is needed, a new keyring is created here.
        """
        try:
            temp_pgproot = os.path.join(GLSettings.pgproot, "%s" % rstr.xeger(r'[A-Za-z0-9]{8}'))
            os.makedirs(temp_pgproot, mode=0700)
            self.pgph = GPG(gnupghome=temp_pgproot, options=['--trust-model', 'always'])
            self.pgph.encoding = "UTF-8"
        except OSError as ose:
            log.err("Critical, OS error in operating with GnuPG home: %s" % ose)
            raise
        except Exception as excep:
            log.err("Unable to instance PGP object: %s" % excep)
            raise

    def load_key(self, key):
        """
        @param key:
        @return: True or False, True only if a key is effectively importable and listed.
        """
        try:
            import_result = self.pgph.import_keys(key)
        except Exception as excep:
            log.err("Error in PGP import_keys: %s" % excep)
            raise errors.PGPKeyInvalid

        if len(import_result.fingerprints) != 1:
            raise errors.PGPKeyInvalid

        fingerprint = import_result.fingerprints[0]

        # looking if the key is effectively reachable
        try:
            all_keys = self.pgph.list_keys()
        except Exception as excep:
            log.err("Error in PGP list_keys: %s" % excep)
            raise errors.PGPKeyInvalid

        info = u""
        expiration = datetime.utcfromtimestamp(0)
        for key in all_keys:
            if key['fingerprint'] == fingerprint:

                if key['expires']:
                    expiration = datetime.utcfromtimestamp(int(key['expires']))
                    exp_date = datetime_to_day_str(expiration)
                else:
                    exp_date = u'Never'

                info += "Key length: %s\n" % key['length']
                info += "Key expiration: %s\n" % exp_date

                try:
                    for uid in key['uids']:
                        info += "\t%s\n" % uid
                except Exception as excep:
                    log.err("Error in PGP key format/properties: %s" % excep)
                    raise errors.PGPKeyInvalid

                break

        if not len(info):
            log.err("Key apparently imported but unable to reload it")
            raise errors.PGPKeyInvalid

        return {
            'fingerprint': fingerprint,
            'expiration': expiration,
            'info': info
        }

    def encrypt_file(self, key_fingerprint, plainpath, filestream, output_path):
        """
        @param pgp_key_public:
        @param plainpath:
        @return:
        """
        encrypt_obj = self.pgph.encrypt_file(filestream, str(key_fingerprint))

        if not encrypt_obj.ok:
            raise errors.PGPKeyInvalid

        log.debug("Encrypting for key %s file %s (%d bytes)" %
                  (key_fingerprint,
                   plainpath, len(str(encrypt_obj))))

        encrypted_path = os.path.join(os.path.abspath(output_path),
                                      "pgp_encrypted-%s" % rstr.xeger(r'[A-Za-z0-9]{16}'))

        try:
            with open(encrypted_path, "w+") as f:
                f.write(str(encrypt_obj))

            return encrypted_path, len(str(encrypt_obj))
        except Exception as excep:
            log.err("Error in writing PGP file output: %s (%s) bytes %d" %
                    (excep.message, encrypted_path, len(str(encrypt_obj)) ))
            raise errors.InternalServerError("Error in writing [%s]" % excep.message)

    def encrypt_message(self, key_fingerprint, plaintext):
        """
        @param plaindata:
            An arbitrary long text that would be encrypted

        @param receiver_desc:

            The output of
                globaleaks.handlers.admin.admin_serialize_receiver()
            dictionary. It contain the fingerprint of the Receiver PUBKEY

        @return:
            The unicode of the encrypted output (armored)

        """
        # This second argument may be a list of fingerprint, not just one
        encrypt_obj = self.pgph.encrypt(plaintext, str(key_fingerprint))

        if not encrypt_obj.ok:
            raise errors.PGPKeyInvalid

        log.debug("Encrypting for key %s %d byte of plain data (%d cipher output)" %
                  (key_fingerprint,
                   len(plaintext), len(str(encrypt_obj))))

        return str(encrypt_obj)

    def destroy_environment(self):
        try:
            shutil.rmtree(self.pgph.gnupghome)
        except Exception as excep:
            log.err("Unable to clean temporary PGP environment: %s: %s" % (self.pgph.gnupghome, excep))
예제 #36
0
class GLBPGP(object):
    """
    PGP has not a dedicated class, because one of the function is called inside a transact, and
    I'm not quite confident on creating an object that operates on the filesystem knowing
    that would be run also on the Storm cycle.
    """
    def __init__(self):
        """
        every time is needed, a new keyring is created here.
        """
        try:
            temp_pgproot = os.path.join(GLSettings.pgproot,
                                        "%s" % generateRandomKey(8))
            os.makedirs(temp_pgproot, mode=0700)
            self.gnupg = GPG(gnupghome=temp_pgproot,
                             options=['--trust-model', 'always'])
            self.gnupg.encoding = "UTF-8"
        except OSError as ose:
            log.err("Critical, OS error in operating with GnuPG home: %s" %
                    ose)
            raise
        except Exception as excep:
            log.err("Unable to instance PGP object: %s" % excep)
            raise

    def load_key(self, key):
        """
        @param key:
        @return: True or False, True only if a key is effectively importable and listed.
        """
        try:
            import_result = self.gnupg.import_keys(key)
        except Exception as excep:
            log.err("Error in PGP import_keys: %s" % excep)
            raise errors.PGPKeyInvalid

        if len(import_result.fingerprints) == 0:
            raise errors.PGPKeyInvalid

        fingerprint = import_result.fingerprints[0]

        # looking if the key is effectively reachable
        try:
            all_keys = self.gnupg.list_keys()
        except Exception as excep:
            log.err("Error in PGP list_keys: %s" % excep)
            raise errors.PGPKeyInvalid

        expiration = datetime.utcfromtimestamp(0)
        for key in all_keys:
            if key['fingerprint'] == fingerprint:
                if key['expires']:
                    expiration = datetime.utcfromtimestamp(int(key['expires']))
                break

        return {
            'fingerprint': fingerprint,
            'expiration': expiration,
        }

    def encrypt_file(self, key_fingerprint, input_file, output_path):
        """
        Encrypt a file with the specified PGP key
        """
        encrypted_obj = self.gnupg.encrypt_file(input_file,
                                                str(key_fingerprint),
                                                output=output_path)

        if not encrypted_obj.ok:
            raise errors.PGPKeyInvalid

        return encrypted_obj, os.stat(output_path).st_size

    def encrypt_message(self, key_fingerprint, plaintext):
        """
        Encrypt a text message with the specified key
        """
        encrypted_obj = self.gnupg.encrypt(plaintext, str(key_fingerprint))

        if not encrypted_obj.ok:
            raise errors.PGPKeyInvalid

        return str(encrypted_obj)

    def destroy_environment(self):
        try:
            shutil.rmtree(self.gnupg.gnupghome)
        except Exception as excep:
            log.err("Unable to clean temporary PGP environment: %s: %s" %
                    (self.gnupg.gnupghome, excep))
예제 #37
0
class PGPContext(object):
    """
    PGP does not have a dedicated class, because one of the function is called inside a transact.
    I'm not confident creating an object that operates on the filesystem knowing that
    would be run also on the Storm cycle.
    """
    def __init__(self, tempdirprefix=None):
        """
        every time is needed, a new keyring is created here.
        """
        if tempdirprefix is None:
            tempdir = tempfile.mkdtemp()
        else:
            tempdir = tempfile.mkdtemp(prefix=tempdirprefix)

        try:
            gpgbinary = 'gpg'
            if os.path.exists('/usr/bin/gpg1'):
                gpgbinary = 'gpg1'

            self.gnupg = GPG(gpgbinary=gpgbinary,
                             gnupghome=tempdir,
                             options=['--trust-model', 'always'])
            self.gnupg.encoding = "UTF-8"
        except OSError as excep:
            log.err("Critical, OS error in operating with GnuPG home: %s",
                    excep)
            raise
        except Exception as excep:
            log.err("Unable to instance PGP object: %s" % excep)
            raise

    def load_key(self, key):
        """
        @param key
        @return: a dict with the expiration date and the key fingerprint
        """
        try:
            import_result = self.gnupg.import_keys(key)
        except Exception as excep:
            log.err("Error in PGP import_keys: %s", excep)
            raise errors.InputValidationError

        if not import_result.fingerprints:
            raise errors.InputValidationError

        fingerprint = import_result.fingerprints[0]

        # looking if the key is effectively reachable
        try:
            all_keys = self.gnupg.list_keys()
        except Exception as excep:
            log.err("Error in PGP list_keys: %s", excep)
            raise errors.InputValidationError

        expiration = datetime.utcfromtimestamp(0)
        for k in all_keys:
            if k['fingerprint'] == fingerprint:
                if k['expires']:
                    expiration = datetime.utcfromtimestamp(int(k['expires']))
                break

        return {'fingerprint': fingerprint, 'expiration': expiration}

    def encrypt_file(self, key_fingerprint, input_file, output_path):
        """
        Encrypt a file with the specified PGP key
        """
        encrypted_obj = self.gnupg.encrypt_file(input_file,
                                                str(key_fingerprint),
                                                output=output_path)

        if not encrypted_obj.ok:
            raise errors.InputValidationError

        return encrypted_obj, os.stat(output_path).st_size

    def encrypt_message(self, key_fingerprint, plaintext):
        """
        Encrypt a text message with the specified key
        """
        encrypted_obj = self.gnupg.encrypt(plaintext, str(key_fingerprint))

        if not encrypted_obj.ok:
            raise errors.InputValidationError

        return str(encrypted_obj)

    def __del__(self):
        try:
            shutil.rmtree(self.gnupg.gnupghome)
        except Exception as excep:
            log.err("Unable to clean temporary PGP environment: %s: %s",
                    self.gnupg.gnupghome, excep)
예제 #38
0
class GLBGPG:
    """
    GPG has not a dedicated class, because one of the function is callend inside a transact, and
    I'm not quite confident on creating an object that operates on the filesystem knowing
    that would be run also on the Storm cycle.
    """

    def __init__(self, receiver_desc):
        """
        every time is needed, a new keyring is created here.
        """
        atfork()

        if receiver_desc.has_key('gpg_key_status') and \
           receiver_desc['gpg_key_status'] != Receiver._gpg_types[1]: # Enabled
            log.err("Requested GPG initialization for a receiver without GPG configured! %s" %
                    receiver_desc['username'])
            raise Exception("Requested GPG init for user without GPG [%s]" % receiver_desc['username'])

        try:
            temp_gpgroot = os.path.join(GLSetting.gpgroot, "%s" % random.randint(0, 0xFFFF) )
            os.makedirs(temp_gpgroot, mode=0700)
            self.gpgh = GPG(gnupghome=temp_gpgroot, options="--trust-model always")
        except Exception as excep:
            log.err("Unable to instance GPG object: %s" % excep)
            raise excep

        self.receiver_desc = receiver_desc
        log.debug("GPG object initialized for receiver %s" % receiver_desc['username'])

    def sanitize_gpg_string(self, received_gpgasc):
        """
        @param received_gpgasc: A gpg armored key
        @return: Sanitized string or raise InvalidInputFormat

        This function validate the integrity of a GPG key
        """
        lines = received_gpgasc.split("\n")
        sanitized = ""

        start = 0
        if not len(lines[start]):
            start += 1

        if lines[start] != '-----BEGIN PGP PUBLIC KEY BLOCK-----':
            raise errors.InvalidInputFormat("GPG invalid format")
        else:
            sanitized += lines[start] + "\n"

        i = 0
        while i < len(lines):

            # the C language as left some archetypes in my code
            # [ITA] https://www.youtube.com/watch?v=7jI4DnRJP3k
            i += 1

            try:
                if len(lines[i]) < 2:
                    continue
            except IndexError:
                continue

            main_content = re.compile( r"^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$" , re.UNICODE)
            base64only = main_content.findall(lines[i])

            if len(base64only) == 1:
                sanitized += str(base64only[0]) + "\n"

            # this GPG/PGP format it's different from the common base64 ? dunno
            if len(lines[i]) == 5 and lines[i][0] == '=':
                sanitized += str(lines[i]) + "\n"

            if lines[i] == '-----END PGP PUBLIC KEY BLOCK-----':
                sanitized += lines[i] + "\n"
                return sanitized

        raise errors.InvalidInputFormat("Malformed PGP key block")

    def validate_key(self, armored_key):
        """
        @param armored_key:
        @return: True or False, True only if a key is effectively importable and listed.
        """

        # or raise InvalidInputFormat
        sanitized_gpgasc = self.sanitize_gpg_string(armored_key)

        try:
            self.ke = self.gpgh.import_keys(sanitized_gpgasc)
        except Exception as excep:
            log.err("Error in GPG import_keys: %s" % excep)
            return False

        # Error reported in stderr may just be warning, this is because is not raise an exception here
        # if self.ke.stderr:
        #     log.err("Receiver %s in uploaded GPG key has raise and alarm:\n< %s >" %
        #             (self.receiver_desc['username'], (self.ke.stderr.replace("\n", "\n  "))[:-3]))

        if not (hasattr(self.ke, 'results') and len(self.ke.results) == 1 and self.ke.results[0].has_key('fingerprint')):
            log.err("User error: unable to import GPG key in the keyring")
            return False

        # else, the key has been loaded and we extract info about that:
        self.fingerprint = self.ke.results[0]['fingerprint']

        # looking if the key is effectively reachable
        try:
            all_keys = self.gpgh.list_keys()
        except Exception as excep:
            log.err("Error in GPG list_keys: %s" % excep)
            return False

        self.keyinfo = u""
        for key in all_keys:
            if key['fingerprint'] == self.fingerprint:

                self.keyinfo += "Key length %s" % key['length']
                try:
                    for uid in key['uids']:
                        self.keyinfo += "\n\t%s" % uid
                except Exception as excep:
                    log.err("Error in GPG key format/properties: %s" % excep)
                    return False

        if not len(self.keyinfo):
            log.err("Key apparently imported but unable to be extracted info")
            return False

        return True


    def encrypt_file(self, plainpath, filestream, output_path):
        """
        @param gpg_key_armor:
        @param plainpath:
        @return:
        """
        if not self.validate_key(self.receiver_desc['gpg_key_armor']):
            raise errors.GPGKeyInvalid

        encrypt_obj = self.gpgh.encrypt_file(filestream, str(self.receiver_desc['gpg_key_fingerprint']))

        if not encrypt_obj.ok:
            # continue here if is not ok
            log.err("Falure in encrypting file %s %s (%s)" % ( plainpath,
                    self.receiver_desc['username'], self.receiver_desc['gpg_key_fingerprint']) )
            log.err(encrypt_obj.stderr)
            raise errors.GPGKeyInvalid

        log.debug("Encrypting for %s (%s) file %s (%d bytes)" %
                  (self.receiver_desc['username'], self.receiver_desc['gpg_key_fingerprint'],
                  plainpath, len(str(encrypt_obj))) )

        encrypted_path = os.path.join( os.path.abspath(output_path),
                                       "gpg_encrypted-%d-%d" %
                                       (random.randint(0, 0xFFFF), random.randint(0, 0xFFFF)))

        if os.path.isfile(encrypted_path):
            log.err("Unexpected unpredictable unbelievable error! %s" % encrypted_path)
            raise errors.InternalServerError("File conflict in GPG encrypted output")

        try:
            with open(encrypted_path, "w+") as f:
                f.write(str(encrypt_obj))

            return encrypted_path, len(str(encrypt_obj))

        except Exception as excep:
            log.err("Error in writing GPG file output: %s (%s) bytes %d" %
                    (excep.message, encrypted_path, len(str(encrypt_obj)) ))
            raise errors.InternalServerError("Error in writing [%s]" % excep.message )


    def encrypt_message(self, plaintext):
        """
        @param plaindata:
            An arbitrary long text that would be encrypted

        @param receiver_desc:

            The output of
                globaleaks.handlers.admin.admin_serialize_receiver()
            dictionary. It contain the fingerprint of the Receiver PUBKEY

        @return:
            The unicode of the encrypted output (armored)

        """
        if not self.validate_key(self.receiver_desc['gpg_key_armor']):
            raise errors.GPGKeyInvalid

        # This second argument may be a list of fingerprint, not just one
        encrypt_obj = self.gpgh.encrypt(plaintext, str(self.receiver_desc['gpg_key_fingerprint']) )

        if not encrypt_obj.ok:
            # else, is not .ok
            log.err("Falure in encrypting %d bytes for %s (%s)" % (len(plaintext),
                    self.receiver_desc['username'], self.receiver_desc['gpg_key_fingerprint']) )
            log.err(encrypt_obj.stderr)
            raise errors.GPGKeyInvalid

        log.debug("Encrypting for %s (%s) %d byte of plain data (%d cipher output)" %
                  (self.receiver_desc['username'], self.receiver_desc['gpg_key_fingerprint'],
                   len(plaintext), len(str(encrypt_obj))) )

        return str(encrypt_obj)


    def destroy_environment(self):
        try:
            shutil.rmtree(self.gpgh.gnupghome)
        except Exception as excep:
            log.err("Unable to clean temporary GPG environment: %s: %s" % (self.gpgh.gnupghome, excep))
예제 #39
0
class GLBPGP(object):
    """
    PGP has not a dedicated class, because one of the function is called inside a transact, and
    I'm not quite confident on creating an object that operates on the filesystem knowing
    that would be run also on the Storm cycle.
    """
    def __init__(self):
        """
        every time is needed, a new keyring is created here.
        """
        try:
            temp_pgproot = os.path.join(GLSettings.pgproot, "%s" % generateRandomKey(8))
            os.makedirs(temp_pgproot, mode=0700)
            self.gnupg = GPG(gnupghome=temp_pgproot, options=['--trust-model', 'always'])
            self.gnupg.encoding = "UTF-8"
        except OSError as ose:
            log.err("Critical, OS error in operating with GnuPG home: %s" % ose)
            raise
        except Exception as excep:
            log.err("Unable to instance PGP object: %s" % excep)
            raise

    def load_key(self, key):
        """
        @param key:
        @return: True or False, True only if a key is effectively importable and listed.
        """
        try:
            import_result = self.gnupg.import_keys(key)
        except Exception as excep:
            log.err("Error in PGP import_keys: %s" % excep)
            raise errors.PGPKeyInvalid

        if len(import_result.fingerprints) == 0:
            raise errors.PGPKeyInvalid

        fingerprint = import_result.fingerprints[0]

        # looking if the key is effectively reachable
        try:
            all_keys = self.gnupg.list_keys()
        except Exception as excep:
            log.err("Error in PGP list_keys: %s" % excep)
            raise errors.PGPKeyInvalid

        expiration = datetime.utcfromtimestamp(0)
        for key in all_keys:
            if key['fingerprint'] == fingerprint:
                if key['expires']:
                    expiration = datetime.utcfromtimestamp(int(key['expires']))
                break

        return {
            'fingerprint': fingerprint,
            'expiration': expiration,
        }

    def encrypt_file(self, key_fingerprint, input_file, output_path):
        """
        Encrypt a file with the specified PGP key
        """
        encrypted_obj = self.gnupg.encrypt_file(input_file, str(key_fingerprint), output=output_path)

        if not encrypted_obj.ok:
            raise errors.PGPKeyInvalid

        return encrypted_obj,  os.stat(output_path).st_size

    def encrypt_message(self, key_fingerprint, plaintext):
        """
        Encrypt a text message with the specified key
        """
        encrypted_obj = self.gnupg.encrypt(plaintext, str(key_fingerprint))

        if not encrypted_obj.ok:
            raise errors.PGPKeyInvalid

        return str(encrypted_obj)

    def destroy_environment(self):
        try:
            shutil.rmtree(self.gnupg.gnupghome)
        except Exception as excep:
            log.err("Unable to clean temporary PGP environment: %s: %s" % (self.gnupg.gnupghome, excep))
예제 #40
0
class GLBPGP(object):
    """
    PGP has not a dedicated class, because one of the function is called inside a transact, and
    I'm not quite confident on creating an object that operates on the filesystem knowing
    that would be run also on the Storm cycle.
    """

    def __init__(self):
        """
        every time is needed, a new keyring is created here.
        """
        try:
            temp_pgproot = os.path.join(GLSettings.pgproot, "%s" % xeger(r'[A-Za-z0-9]{8}'))
            os.makedirs(temp_pgproot, mode=0700)
            self.pgph = GPG(gnupghome=temp_pgproot, options=['--trust-model', 'always'])
            self.pgph.encoding = "UTF-8"
        except OSError as ose:
            log.err("Critical, OS error in operating with GnuPG home: %s" % ose)
            raise
        except Exception as excep:
            log.err("Unable to instance PGP object: %s" % excep)
            raise

    def load_key(self, key):
        """
        @param key:
        @return: True or False, True only if a key is effectively importable and listed.
        """
        try:
            import_result = self.pgph.import_keys(key)
        except Exception as excep:
            log.err("Error in PGP import_keys: %s" % excep)
            raise errors.PGPKeyInvalid

        if len(import_result.fingerprints) != 1:
            raise errors.PGPKeyInvalid

        fingerprint = import_result.fingerprints[0]

        # looking if the key is effectively reachable
        try:
            all_keys = self.pgph.list_keys()
        except Exception as excep:
            log.err("Error in PGP list_keys: %s" % excep)
            raise errors.PGPKeyInvalid

        info = u""
        expiration = datetime.utcfromtimestamp(0)
        for key in all_keys:
            if key['fingerprint'] == fingerprint:

                if key['expires']:
                    expiration = datetime.utcfromtimestamp(int(key['expires']))
                    exp_date = datetime_to_day_str(expiration)
                else:
                    exp_date = u'Never'

                info += "Key length: %s\n" % key['length']
                info += "Key expiration: %s\n" % exp_date

                try:
                    for uid in key['uids']:
                        info += "\t%s\n" % uid
                except Exception as excep:
                    log.err("Error in PGP key format/properties: %s" % excep)
                    raise errors.PGPKeyInvalid

                break

        if not len(info):
            log.err("Key apparently imported but unable to reload it")
            raise errors.PGPKeyInvalid

        ret = {
            'fingerprint': fingerprint,
            'expiration': expiration,
            'info': info
        }

        return ret

    def encrypt_file(self, key_fingerprint, plainpath, filestream, output_path):
        """
        @param pgp_key_public:
        @param plainpath:
        @return:
        """
        encrypt_obj = self.pgph.encrypt_file(filestream, str(key_fingerprint))

        if not encrypt_obj.ok:
            raise errors.PGPKeyInvalid

        log.debug("Encrypting for key %s file %s (%d bytes)" %
                  (key_fingerprint,
                   plainpath, len(str(encrypt_obj))))

        encrypted_path = os.path.join(os.path.abspath(output_path),
                                      "pgp_encrypted-%s" % xeger(r'[A-Za-z0-9]{16}'))

        try:
            with open(encrypted_path, "w+") as f:
                f.write(str(encrypt_obj))

            return encrypted_path, len(str(encrypt_obj))
        except Exception as excep:
            log.err("Error in writing PGP file output: %s (%s) bytes %d" %
                    (excep.message, encrypted_path, len(str(encrypt_obj)) ))
            raise errors.InternalServerError("Error in writing [%s]" % excep.message)

    def encrypt_message(self, key_fingerprint, plaintext):
        """
        @param plaindata:
            An arbitrary long text that would be encrypted

        @param receiver_desc:

            The output of
                globaleaks.handlers.admin.admin_serialize_receiver()
            dictionary. It contain the fingerprint of the Receiver PUBKEY

        @return:
            The unicode of the encrypted output (armored)

        """
        # This second argument may be a list of fingerprint, not just one
        encrypt_obj = self.pgph.encrypt(plaintext, str(key_fingerprint))

        if not encrypt_obj.ok:
            raise errors.PGPKeyInvalid

        log.debug("Encrypting for key %s %d byte of plain data (%d cipher output)" %
                  (key_fingerprint,
                   len(plaintext), len(str(encrypt_obj))))

        return str(encrypt_obj)

    def destroy_environment(self):
        try:
            shutil.rmtree(self.pgph.gnupghome)
        except Exception as excep:
            log.err("Unable to clean temporary PGP environment: %s: %s" % (self.pgph.gnupghome, excep))
예제 #41
0
def gpg_init_only(tmpdir, benchmark, openpgp_keys, monkeypatch, num_keys):
    keys = openpgp_keys[0:num_keys]
    gpg = GPG(homedir=tmpdir.dirname)
    for key in keys:
        gpg.import_keys(key.key_data)
예제 #42
0
class GLBGPG:
    """
    GPG has not a dedicated class, because one of the function is called inside a transact, and
    I'm not quite confident on creating an object that operates on the filesystem knowing
    that would be run also on the Storm cycle.
    """
    def __init__(self, receiver_desc):
        """
        every time is needed, a new keyring is created here.
        """
        if receiver_desc.has_key('gpg_key_status') and \
                        receiver_desc['gpg_key_status'] != Receiver._gpg_types[1]: # Enabled
            log.err(
                "Requested GPG initialization for a receiver without GPG configured! %s"
                % receiver_desc['username'])
            raise Exception("Requested GPG init for user without GPG [%s]" %
                            receiver_desc['username'])

        try:
            temp_gpgroot = os.path.join(GLSetting.gpgroot,
                                        "%s" % xeger(r'[A-Za-z0-9]{8}'))
            os.makedirs(temp_gpgroot, mode=0700)
            self.gpgh = GPG(gnupghome=temp_gpgroot,
                            options=['--trust-model', 'always'])
        except Exception as excep:
            log.err("Unable to instance GPG object: %s" % excep)
            raise excep

        self.receiver_desc = receiver_desc
        log.debug("GPG object initialized for receiver %s" %
                  receiver_desc['username'])

    def sanitize_gpg_string(self, received_gpgasc):
        """
        @param received_gpgasc: A gpg armored key
        @return: Sanitized string or raise InvalidInputFormat

        This function validate the integrity of a GPG key
        """
        lines = received_gpgasc.split("\n")
        sanitized = ""

        start = 0
        if not len(lines[start]):
            start += 1

        if lines[start] != '-----BEGIN PGP PUBLIC KEY BLOCK-----':
            raise errors.InvalidInputFormat("GPG invalid format")
        else:
            sanitized += lines[start] + "\n"

        i = 0
        while i < len(lines):

            # the C language as left some archetypes in my code
            # [ITA] https://www.youtube.com/watch?v=7jI4DnRJP3k
            i += 1

            try:
                if len(lines[i]) < 2:
                    continue
            except IndexError:
                continue

            main_content = re.compile(
                r"^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$",
                re.UNICODE)
            base64only = main_content.findall(lines[i])

            if len(base64only) == 1:
                sanitized += str(base64only[0]) + "\n"

            # this GPG/PGP format it's different from the common base64 ? dunno
            if len(lines[i]) == 5 and lines[i][0] == '=':
                sanitized += str(lines[i]) + "\n"

            if lines[i] == '-----END PGP PUBLIC KEY BLOCK-----':
                sanitized += lines[i] + "\n"
                return sanitized

        raise errors.InvalidInputFormat("Malformed PGP key block")

    def validate_key(self, armored_key):
        """
        @param armored_key:
        @return: True or False, True only if a key is effectively importable and listed.
        """

        # or raise InvalidInputFormat
        sanitized_gpgasc = self.sanitize_gpg_string(armored_key)

        try:
            key = self.gpgh.import_keys(sanitized_gpgasc)
        except Exception as excep:
            log.err("Error in GPG import_keys: %s" % excep)
            return False

        # Error reported in stderr may just be warning, this is because is not raise an exception here
        # if self.ke.stderr:
        #     log.err("Receiver %s in uploaded GPG key has raise and alarm:\n< %s >" %
        #             (self.receiver_desc['username'], (self.ke.stderr.replace("\n", "\n  "))[:-3]))

        if not (hasattr(key, 'results') and len(key.results) >= 1
                and key.results[0].has_key('fingerprint')):
            log.err("User error: unable to import GPG key in the keyring")
            return False

        # else, the key has been loaded and we extract info about that:
        self.fingerprint = key.results[0]['fingerprint']

        # looking if the key is effectively reachable
        try:
            all_keys = self.gpgh.list_keys()
        except Exception as excep:
            log.err("Error in GPG list_keys: %s" % excep)
            return False

        self.keyinfo = u""
        for key in all_keys:
            if key['fingerprint'] == self.fingerprint:

                self.keyinfo += "Key length %s" % key['length']
                try:
                    for uid in key['uids']:
                        self.keyinfo += "\n\t%s" % uid
                except Exception as excep:
                    log.err("Error in GPG key format/properties: %s" % excep)
                    return False

        if not len(self.keyinfo):
            log.err("Key apparently imported but unable to be extracted info")
            return False

        return True

    def encrypt_file(self, plainpath, filestream, output_path):
        """
        @param gpg_key_armor:
        @param plainpath:
        @return:
        """
        if not self.validate_key(self.receiver_desc['gpg_key_armor']):
            raise errors.GPGKeyInvalid

        encrypt_obj = self.gpgh.encrypt_file(
            filestream, str(self.receiver_desc['gpg_key_fingerprint']))

        if not encrypt_obj.ok:
            # continue here if is not ok
            log.err("Falure in encrypting file %s %s (%s)" %
                    (plainpath, self.receiver_desc['username'],
                     self.receiver_desc['gpg_key_fingerprint']))
            log.err(encrypt_obj.stderr)
            raise errors.GPGKeyInvalid

        log.debug("Encrypting for %s (%s) file %s (%d bytes)" %
                  (self.receiver_desc['username'],
                   self.receiver_desc['gpg_key_fingerprint'], plainpath,
                   len(str(encrypt_obj))))

        encrypted_path = os.path.join(
            os.path.abspath(output_path),
            "gpg_encrypted-%s" % xeger(r'[A-Za-z0-9]{8}'))

        if os.path.isfile(encrypted_path):
            log.err("Unexpected unpredictable unbelievable error! %s" %
                    encrypted_path)
            raise errors.InternalServerError(
                "File conflict in GPG encrypted output")

        try:
            with open(encrypted_path, "w+") as f:
                f.write(str(encrypt_obj))

            return encrypted_path, len(str(encrypt_obj))

        except Exception as excep:
            log.err("Error in writing GPG file output: %s (%s) bytes %d" %
                    (excep.message, encrypted_path, len(str(encrypt_obj))))
            raise errors.InternalServerError("Error in writing [%s]" %
                                             excep.message)

    def encrypt_message(self, plaintext):
        """
        @param plaindata:
            An arbitrary long text that would be encrypted

        @param receiver_desc:

            The output of
                globaleaks.handlers.admin.admin_serialize_receiver()
            dictionary. It contain the fingerprint of the Receiver PUBKEY

        @return:
            The unicode of the encrypted output (armored)

        """
        if not self.validate_key(self.receiver_desc['gpg_key_armor']):
            raise errors.GPGKeyInvalid

        # This second argument may be a list of fingerprint, not just one
        encrypt_obj = self.gpgh.encrypt(
            plaintext, str(self.receiver_desc['gpg_key_fingerprint']))

        if not encrypt_obj.ok:
            # else, is not .ok
            log.err("Falure in encrypting %d bytes for %s (%s)" %
                    (len(plaintext), self.receiver_desc['username'],
                     self.receiver_desc['gpg_key_fingerprint']))
            log.err(encrypt_obj.stderr)
            raise errors.GPGKeyInvalid

        log.debug(
            "Encrypting for %s (%s) %d byte of plain data (%d cipher output)" %
            (self.receiver_desc['username'],
             self.receiver_desc['gpg_key_fingerprint'], len(plaintext),
             len(str(encrypt_obj))))

        return str(encrypt_obj)

    def destroy_environment(self):
        try:
            shutil.rmtree(self.gpgh.gnupghome)
        except Exception as excep:
            log.err("Unable to clean temporary GPG environment: %s: %s" %
                    (self.gpgh.gnupghome, excep))
예제 #43
0
파일: __init__.py 프로젝트: LukeCarrier/hn
    def setUp(self):
        """
        Construct environment.

        Here, we adopt the configuration used by the production or development
        installation and make the necessary changes before writing it to a new
        file in the etc directory. When we're finished, we'll remove it in the
        tearDown() function.
        """

        if not os.path.exists(self.client_env['CONFDIR']):

            # Don't waste time and entropy on keys if we can't write configuration
            # files -- that's a very distressing experience.
            assert len(sys.argv) == 2

            # Prepare two GPG keypairs; one for the agent, one for the client
            agent_gpg_dir  = os.path.join(self.client_env['CONFDIR'], 'agent_gpg')
            agent_gpg      = GPG(gnupghome=agent_gpg_dir)
            agent_key      = agent_gpg.gen_key(agent_gpg.gen_key_input(**self.gpg_params))
            client_gpg_dir = os.path.join(self.client_env['CONFDIR'], 'client_gpg')
            client_gpg     = GPG(gnupghome=client_gpg_dir)
            client_key     = client_gpg.gen_key(client_gpg.gen_key_input(**self.gpg_params))

            # Export both public keys; import them into the opposing side
            agent_key_blob  = agent_gpg.export_keys(agent_key.fingerprint)
            client_gpg.import_keys(agent_key_blob)
            client_gpg.sign_key(agent_key.fingerprint)
            client_key_blob = client_gpg.export_keys(client_key.fingerprint)
            agent_gpg.import_keys(client_key_blob)
            agent_gpg.sign_key(client_key.fingerprint)

            # Configure the agent to run in a development-safe configuration.
            #
            # Here, we load the base configuration we ship with the application
            # as the default. All other configuration will be ignored for the
            # purposes of the test run, since this is outside of our scope.
            with open(self.agent_env['CONFDIR'], 'w') as f:
                l = os.path.join(self.client_env['CONFDIR'], 'agent_%s.log')
                agent_cfg = ConfigurationFactory.get('hypernova.agent',
                                                     root_dir=sys.argv[1])
                agent_cfg.set('server',  'address',     self.agent_addr[0])
                agent_cfg.set('server',  'port',        self.agent_addr[1])
                agent_cfg.set('server',  'daemon',      'false')
                agent_cfg.set('gpg',     'key_store',   agent_gpg_dir)
                agent_cfg.set('gpg',     'fingerprint', agent_key.fingerprint)
                agent_cfg.set('logging', 'main_log',    l %('main'))
                agent_cfg.set('logging', 'request_log', l %('request'))
                agent_cfg.set('logging', 'error_log',   l %('error'))
                agent_cfg.write(f)

            # The client has to use two different configuration files, both in
            # the same directory.
            client_cfg_dir = self.client_env['CONFDIR']

            # Configure the client to use its temporary key.
            #
            # To communicate with the agent (which will be running in a limited
            # testing mode), we'll need to reconfigure the client with a keypair
            # we've imported into the agent. This keystore manipulation has
            # already taken place, so we know the fingerprint of our new private
            # key.
            client_cfg_file = os.path.join(client_cfg_dir, 'client.ini')
            with open(client_cfg_file, 'w') as f:
                client_cfg      = configparser.SafeConfigParser()
                client_cfg.add_section('client')
                client_cfg.set('client', 'privkey', client_key.fingerprint)
                client_cfg.write(f)

            # Pair the client to the agent.
            #
            # We do this manually, since the importer requires that we write the
            # public key to a file before we import it. This would be a
            # pointless exercise and an unnecessary complication.
            client_srv_file = os.path.join(client_cfg_dir, 'servers.ini')
            with open(client_srv_file, 'w') as f:
                client_srv_cfg  = configparser.SafeConfigParser()
                client_srv_cfg.add_section('local')
                client_srv_cfg.set('local', 'addr', ':'.join(self.agent_addr))
                client_srv_cfg.set('local', 'pubkey', agent_key.fingerprint)
                client_srv_cfg.write(f)

        # TODO: instead of lazily and unreliably falling asleep on the job,
        #       we should probably use a regular expression to check the output.
        #       Time is of the essence, though!
        #       No, we'll use pexpect instead, since it's now shipped as a py3k
        #       dependency.
        agent_cmd = [
            'hn-agent',
            self.agent_env['CONFDIR']
        ]
        self.agent_proc = subprocess.Popen(agent_cmd, env=self.agent_env,
                                           stdin=subprocess.PIPE,
                                           stdout=subprocess.PIPE,
                                           stderr=subprocess.PIPE)
        time.sleep(self.agent_init_time)
예제 #44
0
    def _check_openpgp_pubkey_from_file(self, pubkey_file, long_key_id):
        with TemporaryDirectory() as temp_gpg_home:
            gpg = GPG(gnupghome=temp_gpg_home)
            with open(pubkey_file, 'rb') as pubkey_fh:
                import_result = gpg.import_keys(pubkey_fh.read())
            if len(import_result.results) == 0:
                raise Exception(
                    "The OpenPGP file {} contains no OpenPGP keys."
                    " Keys: {}".format(
                        pubkey_file,
                        import_result.results,
                    )
                )
            logging.info("OK - OpenPGP file {pubkey_file} contains one or more OpenPGP key.".format(
                pubkey_file=pubkey_file,
            ))
            fingerprint = [x['fingerprint'] for x in import_result.results if x.get('fingerprint')][0]
            actual_long_key_id = fingerprint[-16:]
            given_long_key_id = re.sub(r'^0x', '', long_key_id)
            if actual_long_key_id.lower() != given_long_key_id.lower():
                raise Exception(
                    textwrap.dedent(
                        """
                        The OpenPGP file {given_long_key_id} contains a different key than what the file name suggests.
                        Key ID from file name: {given_long_key_id},
                        Key ID from pubkey in file: {actual_long_key_id}
                        """
                    ).lstrip().format(
                        given_long_key_id=given_long_key_id,
                        actual_long_key_id=actual_long_key_id,
                    )
                )
            logging.info(
                "OK - OpenPGP file {pubkey_file} contains a OpenPGP public key"
                " whose long key ID matching the file name.".format(
                    pubkey_file=pubkey_file,
                )
            )

            list_key = gpg.list_keys()[0]
            epoch_time = int(time.time())
            expires_time = int(list_key['expires'])
            if self._strict:
                if expires_time < epoch_time:
                    raise Exception(
                        textwrap.dedent(
                            """
                            The OpenPGP file {} contains a expired OpenPGP key.
                            Current date: {}
                            Expiration date: {}
                            """
                        ).lstrip().format(
                            pubkey_file,
                            datetime.fromtimestamp(epoch_time),
                            datetime.fromtimestamp(expires_time),
                        )
                    )
                else:
                    logging.info(
                        "OK - OpenPGP public key from {pubkey_file} is not expired."
                        " Expiration date: {expiration_date}".format(
                            pubkey_file=pubkey_file,
                            expiration_date=datetime.fromtimestamp(expires_time),
                        )
                    )

            # https://keyring.debian.org/creating-key.html
            if self._strict:
                if int(list_key['length']) < self._OPENPGP_MIN_KEY_SIZE:
                    raise Exception(
                        textwrap.dedent(
                            """
                            The OpenPGP file {} contains a weak OpenPGP key.
                            Current key length in bits: {}
                            Expected at least (inclusive): {}
                            """
                        ).lstrip().format(
                            pubkey_file,
                            list_key['length'],
                            self._OPENPGP_MIN_KEY_SIZE,
                        )
                    )
                else:
                    logging.info(
                        "OK - The key length of the OpenPGP public key from {pubkey_file} is not considered to be weak."
                        " Key length in bits: {key_size}".format(
                            pubkey_file=pubkey_file,
                            key_size=list_key['length'],
                        )
                    )

        return True
예제 #45
0
class PGPContext(object):
    def __init__(self, tempdirprefix=None):
        if tempdirprefix is None:
            tempdir = tempfile.mkdtemp()
        else:
            tempdir = tempfile.mkdtemp(prefix=tempdirprefix)

        try:
            self.gnupg = GPG(gnupghome=tempdir,
                             options=['--trust-model', 'always'])
            self.gnupg.encoding = "UTF-8"
        except OSError as excep:
            log.err("Critical, OS error in operating with GnuPG home: %s",
                    excep)
            raise
        except Exception as excep:
            log.err("Unable to instance PGP object: %s" % excep)
            raise

    def load_key(self, key):
        """
        @param key
        @return: a dict with the expiration date and the key fingerprint
        """
        try:
            import_result = self.gnupg.import_keys(key)
        except Exception as excep:
            log.err("Error in PGP import_keys: %s", excep)
            raise errors.InputValidationError

        if not import_result.fingerprints:
            raise errors.InputValidationError

        fingerprint = import_result.fingerprints[0]

        # looking if the key is effectively reachable
        try:
            all_keys = self.gnupg.list_keys()
        except Exception as excep:
            log.err("Error in PGP list_keys: %s", excep)
            raise errors.InputValidationError

        expiration = datetime.utcfromtimestamp(0)
        for k in all_keys:
            if k['fingerprint'] == fingerprint:
                if k['expires']:
                    expiration = datetime.utcfromtimestamp(int(k['expires']))
                break

        return {'fingerprint': fingerprint, 'expiration': expiration}

    def encrypt_file(self, key_fingerprint, input_file, output_path):
        """
        Encrypt a file with the specified PGP key
        """
        encrypted_obj = self.gnupg.encrypt_file(input_file,
                                                key_fingerprint,
                                                output=output_path)

        if not encrypted_obj.ok:
            raise errors.InputValidationError

        return encrypted_obj, os.stat(output_path).st_size

    def encrypt_message(self, key_fingerprint, plaintext):
        """
        Encrypt a text message with the specified key
        """
        encrypted_obj = self.gnupg.encrypt(plaintext, key_fingerprint)

        if not encrypted_obj.ok:
            raise errors.InputValidationError

        return str(encrypted_obj)

    def __del__(self):
        try:
            shutil.rmtree(self.gnupg.gnupghome)
        except Exception as excep:
            log.err("Unable to clean temporary PGP environment: %s: %s",
                    self.gnupg.gnupghome, excep)
예제 #46
0
    def check_git_commits(self, repo_path='.'):
        with TemporaryDirectory() as temp_gpg_home:
            gpg = GPG(gnupghome=temp_gpg_home)

            for long_key_id in os.listdir(self._keyring_name):
                with open(os.path.join(
                    self._keyring_name,
                    long_key_id
                ), 'rb') as pubkey_fh:
                    gpg.import_keys(pubkey_fh.read())

            repo = git.Git(repo_path)
            repo.update_environment(GNUPGHOME=temp_gpg_home)
            commit_count = 0
            # %G?: show "G" for a Good signature,
            #           "B" for a Bad signature,
            #           "U" for a good, untrusted signature and
            #           "N" for no signature
            # TODO 'N' is also returned for signatures made by expired subkeys.
            # Seems to be a bug.
            # Current workaround is only to check the HEAD commit.
            for log_line in [repo.log('--format=%H %G?').split('\n')[0]]:
                (commit_hash, signature_check) = log_line.split(' ')
                commit_count += 1
                if signature_check not in ['U', 'G']:
                    raise Exception(
                        "OpenPGP signature of commit could not be verified."
                        "\nAffected commit:\n{}".format(
                            repo.log('-1', commit_hash),
                        )
                    )
            logging.info(
                textwrap.dedent(
                    """
                    OK - All commits in the repository '{repo_path}' are signed
                    and all public keys to verify the signatures are contained
                    in current HEAD of this repository.
                    """
                ).lstrip().replace('\n', ' ').format(
                    repo_path=repo_path,
                )
            )
            if commit_count <= 0:
                # That condition is expected to never be True because of
                # "returned with exit code 128" for "fatal: bad default revision 'HEAD'".
                # Leaving it in just to be sure (in case git becomes more
                # "friendly" in the future.
                raise Exception(
                    "Expected at least one git commit."
                    " Found {} commits.".format(
                        commit_count,
                    )
                )
            else:
                logging.info(
                    "OK - The repository '{repo_path}' contains at least one commit.".format(
                        repo_path=repo_path,
                    )
                )

        return True
예제 #47
0
파일: openpgp.py 프로젝트: elijh/keymanager
class TempGPGWrapper(object):
    """
    A context manager that wraps a temporary GPG keyring which only contains
    the keys given at object creation.
    """

    def __init__(self, keys=None, gpgbinary=None):
        """
        Create an empty temporary keyring and import any given C{keys} into
        it.

        :param keys: OpenPGP key, or list of.
        :type keys: OpenPGPKey or list of OpenPGPKeys
        :param gpgbinary: Name for GnuPG binary executable.
        :type gpgbinary: C{str}
        """
        self._gpg = None
        self._gpgbinary = gpgbinary
        if not keys:
            keys = list()
        if not isinstance(keys, list):
            keys = [keys]
        self._keys = keys
        for key in keys:
            leap_assert_type(key, OpenPGPKey)

    def __enter__(self):
        """
        Build and return a GPG keyring containing the keys given on
        object creation.

        :return: A GPG instance containing the keys given on object creation.
        :rtype: gnupg.GPG
        """
        self._build_keyring()
        return self._gpg

    def __exit__(self, exc_type, exc_value, traceback):
        """
        Ensure the gpg is properly destroyed.
        """
        # TODO handle exceptions and log here
        self._destroy_keyring()

    def _build_keyring(self):
        """
        Create a GPG keyring containing the keys given on object creation.

        :return: A GPG instance containing the keys given on object creation.
        :rtype: gnupg.GPG
        """
        privkeys = [key for key in self._keys if key and key.private is True]
        publkeys = [key for key in self._keys if key and key.private is False]
        # here we filter out public keys that have a correspondent
        # private key in the list because the private key_data by
        # itself is enough to also have the public key in the keyring,
        # and we want to count the keys afterwards.

        privfps = map(lambda privkey: privkey.fingerprint, privkeys)
        publkeys = filter(
            lambda pubkey: pubkey.fingerprint not in privfps, publkeys)

        listkeys = lambda: self._gpg.list_keys()
        listsecretkeys = lambda: self._gpg.list_keys(secret=True)

        self._gpg = GPG(binary=self._gpgbinary,
                        homedir=tempfile.mkdtemp())
        leap_assert(len(listkeys()) is 0, 'Keyring not empty.')

        # import keys into the keyring:
        # concatenating ascii-armored keys, which is correctly
        # understood by GPG.

        self._gpg.import_keys("".join(
            [x.key_data for x in publkeys + privkeys]))

        # assert the number of keys in the keyring
        leap_assert(
            len(listkeys()) == len(publkeys) + len(privkeys),
            'Wrong number of public keys in keyring: %d, should be %d)' %
            (len(listkeys()), len(publkeys) + len(privkeys)))
        leap_assert(
            len(listsecretkeys()) == len(privkeys),
            'Wrong number of private keys in keyring: %d, should be %d)' %
            (len(listsecretkeys()), len(privkeys)))

    def _destroy_keyring(self):
        """
        Securely erase the keyring.
        """
        # TODO: implement some kind of wiping of data or a more
        # secure way that
        # does not write to disk.

        try:
            for secret in [True, False]:
                for key in self._gpg.list_keys(secret=secret):
                    self._gpg.delete_keys(
                        key['fingerprint'],
                        secret=secret)
            leap_assert(len(self._gpg.list_keys()) is 0, 'Keyring not empty!')

        except:
            raise

        finally:
            leap_assert(self._gpg.homedir != os.path.expanduser('~/.gnupg'),
                        "watch out! Tried to remove default gnupg home!")
            shutil.rmtree(self._gpg.homedir)
예제 #48
0
파일: pgp.py 프로젝트: chojar/GlobaLeaks
class PGPContext(object):
    def __init__(self, tempdirprefix=None):
        if tempdirprefix is None:
            tempdir = tempfile.mkdtemp()
        else:
            tempdir = tempfile.mkdtemp(prefix=tempdirprefix)

        try:
            gpgbinary='gpg'
            if os.path.exists('/usr/bin/gpg1'):
                gpgbinary='gpg1'

            self.gnupg = GPG(gpgbinary=gpgbinary, gnupghome=tempdir, options=['--trust-model', 'always'])
            self.gnupg.encoding = "UTF-8"
        except OSError as excep:
            log.err("Critical, OS error in operating with GnuPG home: %s", excep)
            raise
        except Exception as excep:
            log.err("Unable to instance PGP object: %s" % excep)
            raise

    def load_key(self, key):
        """
        @param key
        @return: a dict with the expiration date and the key fingerprint
        """
        try:
            import_result = self.gnupg.import_keys(key)
        except Exception as excep:
            log.err("Error in PGP import_keys: %s", excep)
            raise errors.InputValidationError

        if not import_result.fingerprints:
            raise errors.InputValidationError

        fingerprint = import_result.fingerprints[0]

        # looking if the key is effectively reachable
        try:
            all_keys = self.gnupg.list_keys()
        except Exception as excep:
            log.err("Error in PGP list_keys: %s", excep)
            raise errors.InputValidationError

        expiration = datetime.utcfromtimestamp(0)
        for k in all_keys:
            if k['fingerprint'] == fingerprint:
                if k['expires']:
                    expiration = datetime.utcfromtimestamp(int(k['expires']))
                break

        return {
            'fingerprint': fingerprint,
            'expiration': expiration
        }

    def encrypt_file(self, key_fingerprint, input_file, output_path):
        """
        Encrypt a file with the specified PGP key
        """
        encrypted_obj = self.gnupg.encrypt_file(input_file, str(key_fingerprint), output=output_path)

        if not encrypted_obj.ok:
            raise errors.InputValidationError

        return encrypted_obj, os.stat(output_path).st_size

    def encrypt_message(self, key_fingerprint, plaintext):
        """
        Encrypt a text message with the specified key
        """
        encrypted_obj = self.gnupg.encrypt(plaintext, str(key_fingerprint))

        if not encrypted_obj.ok:
            raise errors.InputValidationError

        return str(encrypted_obj)

    def __del__(self):
        try:
            shutil.rmtree(self.gnupg.gnupghome)
        except Exception as excep:
            log.err("Unable to clean temporary PGP environment: %s: %s", self.gnupg.gnupghome, excep)