예제 #1
0
파일: crypt.py 프로젝트: niklasad1/crypt
def encrypt(file):
  gpg_home = find_gpg_keys()
  if ( gpg_home == ''):
    print 'GPG keys not found'
    sys.exit(1)
  gpg = GPG(gnupghome=gpg_home, use_agent=True)
  public_keys = gpg.list_keys()
  key_id = public_keys[0]['keyid']

  if ( os.path.isfile(file)):
      if ( file.endswith('.gpg')):
        print file + ' is already encrypted'
      else:
        stream = open(file, "rb")
        status = gpg.encrypt_file(stream, key_id, passphrase='default_key', armor=False, always_trust=True,
                         output=file+'.gpg', symmetric=False)
        stream.close()
        if ( status.ok):
          os.remove(file)
          print file , ' successfully encrypted'
  elif (os.path.isdir(file)):
    for root, dirs, files in os.walk(file, topdown=True):
      for name in files:
        current_file = (os.path.join(root, name))
        if ( current_file.endswith('.gpg') ):
          print current_file + ' : is already encrypted'
        else:
          stream = open(current_file, "rb")
          status = gpg.encrypt_file(stream, key_id, armor=True, always_trust=True, symmetric=False, output=current_file+'.gpg')
          stream.close()
          if ( status.ok ):
            os.remove(current_file)
            print current_file + ' successfully encrypted'
  else:
    print 'ERROR, file or directory not found'
예제 #2
0
    def execute(self):
        gpg_home = os.path.join(os.path.expanduser('~'), '.gnupg/')
        default_recpipient = os.environ['DEFAULT_RECIPIENT']

        if not default_recpipient:
            self.fm.notify(
                'DEFAULT_RECIPIENT environment variable must be set')
            return

        gpg = GPG(gpgbinary='/usr/bin/gpg', gnupghome=gpg_home)

        paths = [
            os.path.basename(f.path) for f in self.fm.thistab.get_selection()
        ]

        for p in paths:
            if os.path.isdir(p):
                new_p = self.tardir(p)
                run(['rm', '-rf', p])
                p = new_p

            with open(p, 'rb') as f:
                enc = gpg.encrypt_file(f, default_recpipient)

            with open(p + '.gpg', 'wb+') as out:
                out.write(enc.data)

            if os.path.isfile(p):
                os.remove(p)
예제 #3
0
 def __call__(self):
     fileName = as_human_readable(self.get_chosen_files()[0])
     gpg = GPG()
     default_recipient = self._get_default_recipient()
     recipient, ok = show_prompt('Recipient', default=default_recipient)
     with open(fileName, 'rb') as f:
         status = gpg.encrypt_file(f,
                                   recipients=[recipient],
                                   output=fileName + '.gpg')
     show_alert('Status: ' + status.status)
예제 #4
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}]')
예제 #5
0
def decrypt_files(path, gpg: gnupg.GPG):
    for files in os.listdir(path):
        actual_path = path + "/" + files
        if os.path.isfile(actual_path):
            if files.endswith(".gpg"):
                logger.debug(f"decrypting: {actual_path}")
                with open(actual_path, "rb") as reader:
                    print(gpg.decrypt_file(reader, passphrase=__passphrase__, output=actual_path).status)
                logger.debug(f"encrypting: {actual_path}")
                with open(actual_path, "rb") as reader:
                    print(gpg.encrypt_file(reader, recipients=__newkeyid__, output=actual_path).status)
        else:
            decrypt_files(actual_path, gpg)
예제 #6
0
def encrypt_file(filename):
    cfg = ConfigFromJSON(section='gpg')

    if not op.exists(filename):
        raise ValueError('File {} not exisit'.format(filename))

    gpg = GPG()
    target = ".".join([filename, 'gpg'])
    with open(filename, 'rb') as f:
        enc = gpg.encrypt_file(f, None, symmetric=True, passphrase=cfg.passphrase, output=target)
    if not enc.ok:
        raise RuntimeError(enc.status)

    return target
예제 #7
0
def createciphermsgs_gpg(jt65msgcount, stegmsg, recipient, verbose=False):
# Performs the actual GPG encryption

    ciphermsgs = []

    while len(stegmsg) % 8:
        stegmsg += " "

    gpg = GPG()
    stegstream = io.StringIO(unicode(stegmsg))
    cipherdata = gpg.encrypt_file(stegstream, recipient)

    if cipherdata == "":
        print "You must set the recipient's trust level to -something- in your keyring before we can encrypt the message"
        sys.exit(0)

    cipherlist = list(bytearray(str(cipherdata)))

    if verbose:
        print "Cipher list: " + str(cipherlist)

    if jt65msgcount * 8 < len(cipherlist):
        print(
            "Length of hidden message exceeds capacity of number of valid JT65 messages provided")
        sys.exit(0)

    # Is the total length too big to fit into our max number of packets?
    if len(cipherlist) > MAX_MULTI_PACKET_STEG_BYTES_GPG:
        print("Length of hidden message exceeds capacity of multi-packet steg")
        sys.exit(0)
    totalpackets = len(cipherlist) / 8

    createciphermsgs_packer_other(
        totalpackets, ciphermsgs, cipherlist, verbose)

    return ciphermsgs
예제 #8
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)
예제 #9
0
class gpg(object):
    """
    module to wrap the gnupg library and gpg binary
    """
    def __init__(self, folder_path=None, binary_path=None):
        # ugly but working
        if binary_path is None:
            binary_path = join(project_base, "gpg", "gpg.exe")
            if not isfile(binary_path):
                binary_path = join(project_base, 'gpg')
                if not isfile(binary_path):
                    binary_path = find_executable('gpg')
                    if not isfile(binary_path):
                        raise RuntimeError('gpg not found')
        self.gpg = GPG(
            binary_path,  # gpgbinary
            folder_path,  # gnupghome
            verbose=False,
            options=["--allow-non-selfsigned-uid"])

    def get_key(self, fingerprint, private, passphrase):
        """
        returns the key belonging to the fingerprint given. if 'private' is
        True, the private key is returned. If 'private' is False, the public
        key will be returned.
        """
        key = self.gpg.export_keys(fingerprint,
                                   private,
                                   armor=False,
                                   passphrase=passphrase)
        return b64encode(key)

    def add_keypair(self, public_key, private_key, site, user, passphrase):
        """
        add a keypair into the gpg key database
        """
        try:
            result1 = self.gpg.import_keys(b64decode(public_key))
            result2 = self.gpg.import_keys(b64decode(private_key))
        except TypeError as error:
            getLogger(__name__).critical("add_keypair TypeError " + str(error))
        # make sure this is a key _pair_
        try:
            assert result1.fingerprints[0] == result2.fingerprints[0]
        except (IndexError, AssertionError) as error:
            getLogger(__name__).exception(
                'add_keypair IndexError/AssertionError: ' + str(error))
            return None
        fingerprint = result1.fingerprints[0]

        if self.is_passphrase_valid(passphrase=passphrase,
                                    fingerprint=fingerprint):
            old_fingerprint = self.get_fingerprint(site, user)
            if not old_fingerprint:
                sql = "INSERT INTO keys (site, user, fingerprint) VALUES (?, ?, ?)"
                database_execute(sql, (site, user, fingerprint))
            else:
                sql = "UPDATE keys SET SITE=? WHERE fingerprint=?"
                database_execute(sql, (site, old_fingerprint))
                if fingerprint != old_fingerprint:
                    getLogger(__name__).warn('updating %s fingerprint to %s' %
                                             (user, fingerprint))
            return fingerprint
        else:
            return None

    def add_public_key(self, site, user, public_key):
        """
        add a public key into the gpg key database
        """
        try:
            result1 = self.gpg.import_keys(b64decode(public_key))
            fingerprint = result1.fingerprints[0]

            sql = "INSERT INTO keys (site, user, fingerprint) VALUES (?, ?, ?)"
            database_execute(sql, (site, user, fingerprint))
            return fingerprint
        except TypeError as error:
            getLogger(__name__).critical("add_public_key TypeError " +
                                         str(error))
        except DatabaseError as error:
            getLogger(__name__).critical("add_public_key DatabaseError " +
                                         str(error))

    def is_passphrase_valid(self,
                            passphrase,
                            label=None,
                            user=None,
                            fingerprint=None):
        if not fingerprint:
            fingerprint = self.get_fingerprint(label, user)

        sign_result = self.gpg.sign("test",
                                    keyid=fingerprint,
                                    passphrase=passphrase)

        return sign_result.data != ''

    def generate(self, passphrase, site, user):
        """
        Generate a new 2048 bit GPG key and add it to the gpg manager.
        """
        data = self.gpg.gen_key_input(key_length=2048, passphrase=passphrase)
        dat = self.gpg.gen_key(data)
        fingerprint = dat.fingerprint
        sql = "INSERT INTO keys (site, user, fingerprint) VALUES (?, ?, ?);"
        database_execute(sql, (site, user, fingerprint))
        return fingerprint

    def get_fingerprint(self, site, user):
        sql = "select fingerprint from keys where site = ? and user = ?"
        result = database_execute(sql, (site, user))
        if not len(result):
            return None
        return result[0][0]

    def has_key(self, site, user):
        """
        Check whether a key is present for a certain site and user
        """
        return self.get_fingerprint(site, user) is None

    def encrypt(self, data, site, user, armor=False):
        """
        encrypt data for user at site.
        """
        fingerprint = self.get_fingerprint(site, user)
        cryptdata = self.gpg.encrypt_file(StringIO(data),
                                          fingerprint,
                                          always_trust=True,
                                          armor=armor)
        return str(cryptdata)

    def decrypt(self, data, passphrase):
        """
        decrypt data received from site.
        """
        datafile = StringIO(data)
        result = self.gpg.decrypt_file(datafile,
                                       passphrase=passphrase,
                                       always_trust=True)
        return str(result)

    @staticmethod
    def add_pkcs7_padding(contents):
        # Input strings must be a multiple of the segment size 16 bytes in length
        segment_size = 16

        # calculate how much padding is needed
        old_contents_length = len(contents)
        next_mult = old_contents_length + (segment_size -
                                           old_contents_length % segment_size)
        getLogger(__name__).debug(
            'old contents length %s || new contents length %s' %
            (old_contents_length, next_mult))

        # do the padding
        padding_byte = chr(next_mult - old_contents_length)
        contents = contents.ljust(next_mult, padding_byte)

        return contents

    @staticmethod
    def remove_pkcs7_padding(contents):
        """
        Remove PKCS#7 padding bytes

        >>> gpg.remove_pkcs7_padding('some_content'.ljust(16, chr(4)))
        'some_content'

        >>> gpg.remove_pkcs7_padding('some_content')
        'some_content'

        >>> gpg.remove_pkcs7_padding('')
        ''

        :param contents:
        :return: contents without padding
        """
        if len(contents) < 1:
            getLogger(__name__).debug(
                'contents is empty. No PKCS#7 padding removed')
            return contents

        bytes_to_remove = ord(contents[-1])  # will work up to 255 bytes

        # check if contents have valid PKCS#7 padding
        if bytes_to_remove > 1 and contents[-2] != contents[-1]:
            getLogger(__name__).debug('no PKCS#7 padding detected')
            return contents

        getLogger(__name__).debug('removing %s bytes of PKCS#7 padding' %
                                  bytes_to_remove)
        return contents[0:(len(contents) - bytes_to_remove)]
예제 #10
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))
예제 #11
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)
예제 #12
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))
예제 #13
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))
예제 #14
0
from ftplib import FPT

# Create instance and set gpg working directory
gpg = GPG(gnupghome=".gpg")

# import an existing public key
with open("mykey.asc", 'r') as fp:
    key_data = fp.read()
    import_status = gpg.import_keys(key_data)
    print("ok: {}".format(import_status.results["ok"]))
    print("text: {}".format(import_status.results["text"]))

# Encrypt a file using the public key.
with open("plain.txt", 'rb') as fp:
    encrypted_file = "encrypted.asc"
    encrypt_status = gpg.encrypt_file(fp,
                                      recipients=import_status.fingerprints,
                                      always_trust=True,
                                      output=encrypted_file)
    print("ok {}".format(encrypt_status.ok))
    print("text: {}".format(encrypt_status.text))
    print("stderr: {}".format(encrypt_status.stderr))

# FTP the file
with FTP("ftp.somehost.com") as ftp:
    ftp.connect("a_username", "a_password")
    fp = open(encrypted_file, 'rb')
    ftp.storbinary("STOR {}".format(encrypted_file), fp)
    ftp.quit()

fp.close()
예제 #15
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)
예제 #16
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))
예제 #17
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))
예제 #18
0
class GLBGPG(object):
    """
    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):
        """
        every time is needed, a new keyring is created here.
        """
        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'])
            self.gpgh.encoding = "UTF-8"
        except Exception as excep:
            log.err("Unable to instance GPG object: %s" % excep)
            raise excep

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

        This function validate the integrity of a GPG key
        """
        lines = key.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 has 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 load_key(self, key):
        """
        @param key:
        @return: True or False, True only if a key is effectively importable and listed.
        """
        try:
            sanitized_key = self.sanitize_gpg_string(key)
            import_result = self.gpgh.import_keys(sanitized_key)
        except Exception as excep:
            log.err("Error in GPG import_keys: %s" % excep)
            raise errors.GPGKeyInvalid

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

        fingerprint = import_result.fingerprints[0]

        # 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)
            raise errors.GPGKeyInvalid

        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 GPG key format/properties: %s" % excep)
                    raise errors.GPGKeyInvalid

                break

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

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

        return ret

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

        if not encrypt_obj.ok:
            raise errors.GPGKeyInvalid

        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),
            "gpg_encrypted-%s" % xeger(r'[A-Za-z0-9]{8}'))
        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, 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.gpgh.encrypt(plaintext, str(key_fingerprint))

        if not encrypt_obj.ok:
            raise errors.GPGKeyInvalid

        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.gpgh.gnupghome)
        except Exception as excep:
            log.err("Unable to clean temporary GPG environment: %s: %s" %
                    (self.gpgh.gnupghome, excep))
예제 #19
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))