예제 #1
0
def gen_pass_query(password, user_id, path_to_user_folder, name):
    print('1')
    val_old = '/'
    part = name.split('/')

    if not path.isdir(path_to_user_folder + '/' + '/'.join(part[:-1])):
        makedirs(path_to_user_folder + '/' + '/'.join(part[:-1]))

    gpg = GPG()
    gpg.encrypt(
        password,
        recipients=['user_' + user_id],
        output=path_to_user_folder + '/' + name + '.gpg',
    )
예제 #2
0
def encrypt_archive(config, workspace, passcode):
    narrate("Encrypting the archive")

    with cd(workspace):
        run('tar -cf archive.tgz archive', 'soEW')
        with open('archive.tgz', 'rb') as f:
            cleartext = f.read()

        gpg = GPG()
        encrypted = gpg.encrypt(
            cleartext,
            recipients=None,
            symmetric=True,
            passphrase=str(passcode),
        )
        if encrypted.ok:
            with open('archive.tgz.gpg', 'w') as f:
                f.write(str(encrypted))
        else:
            raise EncryptionFailed(encrypted)

        rm('archive.tgz', 'archive')

    script = workspace / 'decrypt.sh'
    script.write_text('''\
#!/bin/sh
# Decrypts the archive.

gpg -d -o - archive.tgz.gpg | tar xvf -
''')
    chmod(0o700, script, workspace / 'archive.tgz.gpg')
    narrate(f"Local archive '{workspace.name}' created.")
예제 #3
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])
예제 #4
0
def finish_auth_pass(message, bot):
    t_str = 'test_ur_crappy_password_str'
    decrypt = None

    try:
        gpg = GPG()
        encrypt = gpg.encrypt(t_str, recipients='user_' + str(message.chat.id))
        decrypt = gpg.decrypt(str(encrypt), passphrase=str(message.text))
        system('echo RELOADAGENT | gpg-connect-agent')

    except:
        msg = bot.send_message(message.chat.id, 'Произошла ошибка.')
        del_mess(msg, bot, 4)
        result_available.set()

    if str(decrypt) == t_str:
        global pas
        msg = bot.send_message(message.chat.id, 'Вы аутентифицировались.')
        pas = str(message.text)
        del_mess(msg, bot, 4)
        result_available.set()

    else:
        msg = bot.send_message(message.chat.id, 'Пароль не верен.')
        del_mess(msg, bot, 4)
        result_available.set()
예제 #5
0
class reqPGP(object):
    def __init__(self, path=None):
        self.gpg = GPG(gpgbinary=('../gpg.exe' if osName == 'nt' else 'gpg'))
        if not path:
            try:
                self.path = environ["HOME"] + '/'
            except KeyError:
                self.path = environ["HOMEPATH"] + '\\'
        else:
            if path[-1] != '\\' and osName == 'nt':
                path += '\\'
            elif path[-1] != '/' and osName == 'posix':
                path += '/'
            self.path = path
            

    def genKey(self, account, passphrase):
        input_data = self.gpg.gen_key_input(
            name_email=account,
            passphrase=passphrase)
        self.gpg.gen_key(input_data)

    def encryptFile(self, account, data):
        encryptedData = str(self.gpg.encrypt(data, account))
        with open(self.path + '.' + account + '.req', 'w') as f:
            f.write(encryptedData)

    def decryptFile(self, account, passphrase):
        with open(self.path + '.' + account + '.req', 'rb') as f:
            decryptedData = str(self.gpg.decrypt_file(f, passphrase=passphrase))
        return decryptedData
    
    def deleteKey(self, keyId):
        self.gpg.delete_keys(keyId, True)
        self.gpg.delete_keys(keyId)
예제 #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 finish_clone_pass(message, bot, path_to_user_folder):

	t_str = 'test_ur_crappy_password_str'
	decrypt = None

	try:
		gpg = GPG()
		encrypt = gpg.encrypt(t_str, recipients='user_'+str(message.chat.id))
		decrypt = gpg.decrypt(str(encrypt), passphrase=message.text)
		system('echo RELOADAGENT | gpg-connect-agent')

	except:
	 	msg = bot.send_message(message.chat.id, 'Произошла ошибка.')
	 	del_mess(msg, bot, 8)
	 	return

	if str(decrypt) == t_str:
		try:
			with open(path_to_user_folder+'/user_data/Nothing.txt', 'w') as f:
				f.write(message.text)
			msg = bot.send_message(message.chat.id, 'Пароль сохранен.', reply_markup = types.ReplyKeyboardRemove(selective=False))
			del_mess(msg, bot, 8)
			return

		except:
			msg = bot.send_message(message.chat.id, 'Произошла ошибка.', reply_markup = types.ReplyKeyboardRemove(selective=False))
			del_mess(msg, bot, 8)
			return

	else:
		msg = bot.send_message(message.chat.id, 'Пароль не верен.')
		msg_handler = bot.send_message(message.chat.id, 'Введите пароль от нового ключа, я его сохраню.', reply_markup = types.ReplyKeyboardRemove(selective=False))
		bot.register_next_step_handler(msg_handler, lambda msg: finish_clone_pass(msg, bot, path_to_user_folder))
예제 #8
0
class reqPGP(object):
    def __init__(self, path=None):
        self.gpg = GPG(gpgbinary=('../gpg.exe' if osName == 'nt' else 'gpg'))
        if not path:
            try:
                self.path = environ["HOME"] + '/'
            except KeyError:
                self.path = environ["HOMEPATH"] + '\\'
        else:
            if path[-1] != '\\' and osName == 'nt':
                path += '\\'
            elif path[-1] != '/' and osName == 'posix':
                path += '/'
            self.path = path

    def genKey(self, account, passphrase):
        input_data = self.gpg.gen_key_input(name_email=account,
                                            passphrase=passphrase)
        self.gpg.gen_key(input_data)

    def encryptFile(self, account, data):
        encryptedData = str(self.gpg.encrypt(data, account))
        with open(self.path + '.' + account + '.req', 'w') as f:
            f.write(encryptedData)

    def decryptFile(self, account, passphrase):
        with open(self.path + '.' + account + '.req', 'rb') as f:
            decryptedData = str(self.gpg.decrypt_file(f,
                                                      passphrase=passphrase))
        return decryptedData

    def deleteKey(self, keyId):
        self.gpg.delete_keys(keyId, True)
        self.gpg.delete_keys(keyId)
예제 #9
0
def rm_and_create_file(message, bot, file, name):
    try:
        gpg = GPG()
        remove(file + '.gpg')
        gpg.encrypt(
            message.text,
            recipients=['user_' + str(message.chat.id)],
            output=file + '.gpg',
        )

        msg = bot.send_message(message.chat.id,
                               'Запись ' + name + ' изменена.')
        del_mess(msg, bot, 2)
        return

    except:
        msg = bot.send_message(message.chat.id, 'Произошла ошибка.')
        del_mess(msg, bot, 4)
        return
예제 #10
0
def touch_pass_query(message, bot, way, name):
    val_old = '/'
    part = name.split('/')

    try:
        if not path.isdir(way + '/' + '/'.join(part[:-1])):
            makedirs(way + '/' + '/'.join(part[:-1]))

        gpg = GPG()
        gpg.encrypt(
            message.text,
            recipients=['user_' + str(message.chat.id)],
            output=way + '/' + name + '.gpg',
        )

        msg = bot.send_message(message.chat.id,
                               'Запись ' + name + ' добавлена.')
        del_mess(msg, bot, 4)
        return

    except:
        msg = bot.send_message(message.chat.id, 'Произошла ошибка.')
        del_mess(msg, bot, 4)
        return
예제 #11
0
def send_mail(subject, body_text, addr_from, addr_to, fail_silently=False,
              attachments=None, body_html=None):
    """
    Sends a multipart email containing text and html versions which
    are encrypted for each recipient that has a valid gpg key
    installed.
    """

    # Allow for a single address to be passed in.
    if not hasattr(addr_to, "__iter__"):
        addr_to = [addr_to]

    # Obtain a list of the recipients that have gpg keys installed.
    valid_key_addresses = []
    if USE_GNUPG:
        queryset = Address.objects.filter(address__in=addr_to)
        valid_key_addresses = queryset.values_list("address", flat=True)
        # Create the gpg object.
        if valid_key_addresses:
            gpg = GPG(gnupghome=GNUPG_HOME)

    gpg_kwargs = {}
    if ALWAYS_TRUST:
        gpg_kwargs.update({'always_trust':ALWAYS_TRUST})

    # Encrypts body if recipient has a gpg key installed.
    encrypt_if_key = lambda body, addr: (body if addr not in valid_key_addresses
                                         else unicode(gpg.encrypt(body, addr, **gpg_kwargs)))

    # Load attachments and create name/data tuples.
    attachments_parts = []
    if attachments is not None:
        for attachment in attachments:
            with open(attachment, "rb") as f:
                attachments_parts.append((basename(attachment), f.read()))

    # Send emails.
    for addr in addr_to:
        msg = EmailMultiAlternatives(subject, encrypt_if_key(body_text, addr),
            addr_from, [addr])
        if body_html is not None:
            msg.attach_alternative(encrypt_if_key(body_html, addr), "text/html")
        for parts in attachments_parts:
            msg.attach(parts[0]+'.asc' if ADD_EXTENSION else parts[0], encrypt_if_key(parts[1], addr))
        msg.send(fail_silently=fail_silently)
예제 #12
0
파일: gpg.py 프로젝트: bfrascher/passpy
def write_key(path, key_data, gpg_bin, gpg_opts):
    """Encrypt and write a single key file.

    :param str path: The path to the key to decrypt.

    :param str gpg_bin: The path to the gpg binary.

    :param list gpg_opts: The options for gpg.

    """
    gpg = GPG(gpgbinary=gpg_bin, options=gpg_opts)
    gpg_recipients = _get_gpg_recipients(path)
    # pass always ends it's files with an endline
    if not key_data.endswith('\n'):
        key_data += '\n'
    key_data_enc = gpg.encrypt(key_data, gpg_recipients).data
    with open(path, 'wb') as key_file:
        key_file.write(key_data_enc)
예제 #13
0
파일: gpg.py 프로젝트: rbuzatu90/passpy
def write_key(path, key_data, gpg_bin, gpg_opts):
    """Encrypt and write a single key file.

    :param str path: The path to the key to decrypt.

    :param str gpg_bin: The path to the gpg binary.

    :param list gpg_opts: The options for gpg.

    """
    gpg = GPG(gpgbinary=gpg_bin, options=gpg_opts)
    gpg_recipients = _get_gpg_recipients(path)
    # pass always ends it's files with an endline
    if not key_data.endswith('\n'):
        key_data += '\n'
    key_data_enc = gpg.encrypt(key_data, gpg_recipients).data
    with open(path, 'wb') as key_file:
        key_file.write(key_data_enc)
예제 #14
0
class Vault(object):

    def __init__(self):
        self.vault = {}
        self._gpg = GPG()
        self._file_descriptor = None
        self.passphrase = None

    def reload(self):
        if None in (self._file_descriptor, self.passphrase):
            raise RuntimeError('Cannot reload before calling .load()')
        self.load(self._file_descriptor, self.passphrase)

    def load(self, file_descriptor, passphrase):
        self._file_descriptor = file_descriptor
        self.passphrase = passphrase
        self._file_descriptor.seek(0)
        json_ = self._gpg.decrypt_file(self._file_descriptor, passphrase=self.passphrase)
        self.vault = json.loads(str(json_))

    def save(self, file_descriptor=None, passphrase=None):
        if file_descriptor is not None:
            self._file_descriptor = file_descriptor
        if passphrase is not None:
            self.passphrase = passphrase
        self._file_descriptor.seek(0)
        json_ = json.dumps(self.vault)
        encrypted = self._gpg.encrypt(json_, False, passphrase=self.passphrase, symmetric=True)
        self._file_descriptor.write(str(encrypted))

    def __getitem__(self, key):
        return self.vault[key]

    def get(self, name, default=None):
        return self.vault.get(name, default)

    def __setitem__(self, key, value):
        self.vault[key] = value

    def __delitem__(self, key):
        del self._vault[key]

    def list(self):
        return sorted(self._vault.keys())
    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)
예제 #16
0
def send(recipient, email, *words):
    '''
    encrypt, sign, and send a private message to recipient

    `recipient` is the 'nick' (nickname) of the user to whom you wish to send
    the message. `email` is not necessarily an email address, but is used to
    find the GPG key of the recipient.

    use `-` instead of email to send plain text
    '''
    if len(words) > 1 or isinstance(words[0], str):
        text = ' '.join(words).encode()
    else:
        text = words[0]  # as when called by `publish`
    logging.debug('words: %s', words)
    encoded = None
    if email != '-':
        gpg = GPG()
        logging.debug('message before encrypting: %s', text)
        encrypted = gpg.encrypt(
            text,  # pylint: disable=no-member
            [email],
            sign=True,
            armor=False)
        logging.debug('encrypted: %r...', encrypted.data[:64])
        encoded = b58encode(encrypted.data).decode()
        logging.debug('encoded: %s', encoded)
    if text and not encoded:
        if email == '-' or os.getenv('KB_SEND_PLAINTEXT_OK'):
            logging.warning('encryption %s, sending plaintext',
                            'bypassed' if email == '-' else 'failed')
            encoded = text.decode()
        else:
            logging.warning('encryption failed, run with '
                            'KB_SEND_PLAINTEXT_OK=1 to send anyway')
            logging.warning('setting message to "(encryption failed)"')
            encoded = '(encryption failed)'
    CACHED['ircbot'].privmsg(recipient, encoded)
예제 #17
0
파일: views.py 프로젝트: Ernest0x/gpgvote
def vote(request, poll_id):
    if not request.user.is_authenticated():
        return HttpResponseRedirect("/")
    else:
        logged_in = True

    error = ""
    success = ""
    try:
        poll = Poll.objects.get(pk=poll_id)
    except Poll.DoesNotExist:
        raise Http404

    username = request.user.username
    if (
        (not poll.is_allowed_voter(username))
        or poll.has_voted(username)
        or (poll.starts > datetime.datetime.now())
        or (poll.ends < datetime.datetime.now())
    ):
        return HttpResponseRedirect("/mypolls")

    poll_choices = Choice.objects.filter(poll=poll).order_by("id")
    choice_type = "radio"
    if poll.max_choices > 1:
        choice_type = "checkbox"

    vote_tag = ""
    vote_receipt_encrypted = ""

    if request.POST:
        form = Form(request.POST)
        if form.is_valid():
            choices = request.POST.getlist("choices")

            # Check that the submitted choices exist and belong to the poll
            for choice in choices:
                try:
                    c = Choice.objects.get(pk=choice, poll=poll)
                except Choice.DoesNotExist:
                    error = "The submitted choices are not valid choices of the poll"

                    # Check that the submitted choices are between min and max number of choices allowed for the poll
            if len(choices) > poll.max_choices:
                error = "You cannot vote for more than " + str(poll.max_choices) + " choices"
            if len(choices) < poll.min_choices:
                error = "You must vote for at least " + str(poll.min_choices) + " choices"
                if poll.max_choices == 1:  # a better error message for single choice polls
                    error = "You must select a choice"
            if list_has_duplicates(choices):
                error = "Each choice can be selected only once"

            if not error:
                # Construct a unique, random string to use as a vote tag
                while not vote_tag:
                    vote_tag = "".join(random.choice(string.ascii_uppercase + string.digits) for x in range(35))
                    try:
                        v = Vote.objects.get(tag=vote_tag)
                        vote_tag = ""
                    except Vote.DoesNotExist:  # our random string is unique so we can use it as a vote tag
                        # Encrypt the vote tag with user's public pgp key and sign it with the key of the system authority
                        gpg = GPG(gpgbinary=settings.GNUPGBINARY, gnupghome=settings.GNUPGHOME)
                        vote_receipt = """GPGVote: Vote Receipt
---------------------

You are voter: 
  %s

You voted for Poll:
  \'%s\'

Created by: 
  %s

Your Vote Tag is: %s
  
You made the following choices:""" % (
                            request.user.pgpkey.name + " <" + request.user.username + ">",
                            poll.question,
                            poll.creator.pgpkey.name + " <" + poll.creator.username + ">",
                            vote_tag,
                        )

                        for choice in choices:
                            choice = Choice.objects.get(pk=choice, poll=poll)
                            vote_receipt = vote_receipt + "\n  * %s" % choice.choice

                        vote_receipt_encrypted = gpg.encrypt(
                            vote_receipt,
                            request.user.pgpkey.fingerprint,
                            always_trust=True,
                            sign=settings.SYSTEM_KEY_FINGERPRINT,
                            passphrase=settings.SYSTEM_KEY_PASSWD,
                        )
                        # Create the actual vote records in database
                        for choice in choices:
                            vote = Vote(choice=Choice.objects.get(id=choice), tag=vote_tag)
                            vote.save()
                        poll.add_voter(voter=username, To="who_voted")
                        poll.save()

                success = "You have successfully voted for the poll"

    return render_to_response(
        "vote.html",
        {
            "user": username,
            "poll": poll,
            "choices": poll_choices,
            "choice_type": choice_type,
            "error": error,
            "success": success,
            "vote_receipt": vote_receipt_encrypted,
            "logged_in": logged_in,
        },
        context_instance=RequestContext(request),
    )
예제 #18
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))
예제 #19
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)
예제 #20
0
    gpg = GPG(gnupghome='.python-gnupg')
    gpg.encoding = 'utf-8'
    # These commands needed to be run once to generate and save the key
    #input_data = gpg.gen_key_input(key_type="RSA", key_length=2**KEY_EXP)
    #gpg_key = gpg.gen_key(input_data)
    
    # BEGIN BLOCK CIPHER OPERATIONS
    set_run = ['block']
    setup = """\
from __main__ import gpg, message, enctext
"""
    
    # Create cipher, create cipher text for decryption, time operations, update
    # result with each new operation
    algo_run = ['3DES']
    enctext = gpg.encrypt(message, None, symmetric='3DES',
                          passphrase=PASSPHRASE, armor=False)
    enc_run = ['encrypt']
    enc_trial = Timer(
        "gpg.encrypt(message, None, symmetric='3DES', passphrase=PASSPHRASE, armor=False)",
        setup)
    enc_run.append(enc_trial.repeat(RUN_COUNT, 1))
    algo_run.append(enc_run)
    dec_run = ['decrypt']
    dec_trial = Timer(
        "gpg.decrypt(enctext.data, passphrase=PASSPHRASE)",
        setup)
    dec_run.append(dec_trial.repeat(RUN_COUNT, 1))
    algo_run.append(dec_run)
    set_run.append(algo_run)
    
    # Create cipher, create cipher text for decryption, time operations, update
예제 #21
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))
예제 #22
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))
예제 #23
0
class CryptoTxt:
    """Crypto operation provider for plaintext.

    We use GnuPG for now. Support for X.509 and other options might
    appear in the future.
    """

    def __init__(self, gpg_binary, gpg_home):
        """Initialize the GnuPG instance."""

        self.gpg_binary = gpg_binary
        self.gpg_home = gpg_home
        if not GPG:
            raise TracError(_("Unable to load the python-gnupg module. "
                              "Please check and correct your installation."))
        try:
            self.gpg = GPG(gpgbinary=self.gpg_binary, gnupghome=self.gpg_home)
        except ValueError:
            raise TracError(_("Missing the crypto binary. Please check and "
                              "set full path with option 'gpg_binary'."))
        else:
            # get list of available public keys once for later use
            self.pub_keys = self.gpg.list_keys()

    def sign(self, content, private_key=None):
        private_key = self._get_private_key(private_key)

        cipher = self.gpg.sign(content, keyid=private_key, passphrase='')
        return str(cipher)

    def encrypt(self, content, pubkeys):
        # always_trust needed for making it work with just any pubkey
        cipher = self.gpg.encrypt(content, pubkeys, always_trust=True)
        return str(cipher)

    def sign_encrypt(self, content, pubkeys, private_key=None):
        private_key = self._get_private_key(private_key)

        # always_trust needed for making it work with just any pubkey
        cipher = self.gpg.encrypt(content, pubkeys, always_trust=True,
                                  sign=private_key, passphrase='')
        return str(cipher)

    def get_pubkey_ids(self, addr):
        """Find public key with UID matching address to encrypt to."""

        pubkey_ids = []
        if self.pub_keys and 'uids' in self.pub_keys[-1] and \
                'fingerprint' in self.pub_keys[-1]:
            # compile pattern before use for better performance
            rcpt_re = re.compile(addr)
            for k in self.pub_keys:
                for uid in k['uids']:
                    match = rcpt_re.search(uid)
                    if match is not None:
                        # check for key expiration
                        if k['expires'] == '':
                            pubkey_ids.append(k['fingerprint'][-16:])
                        elif (time.time() + 60) < float(k['expires']):
                            pubkey_ids.append(k['fingerprint'][-16:])
                        break
        return pubkey_ids

    def _get_private_key(self, privkey=None):
        """Find private (secret) key to sign with."""

        # read private keys from keyring
        privkeys = self.gpg.list_keys(True)  # True => private keys
        if privkeys > 0 and 'fingerprint' in privkeys[-1]:
            fingerprints = []
            for k in privkeys:
                fingerprints.append(k['fingerprint'])
        else:
            # no private key in keyring
            return None

        if privkey:
            # check for existence of private key received as argument
            # DEVEL: check for expiration as well
            if 7 < len(privkey) <= 40:
                for fp in fingerprints:
                    if fp.endswith(privkey):
                        # work with last 16 significant chars internally,
                        # even if only 8 are required in trac.ini
                        privkey = fp[-16:]
                        break
                # no fingerprint matching key ID
                else:
                    privkey = None
            else:
                # reset invalid key ID
                privkey = None
        else:
            # select (last) private key from keyring
            privkey = fingerprints[-1][-16:]

        return privkey
예제 #24
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))
예제 #25
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)
예제 #26
0
class CryptoTxt:
    """Crypto operation provider for plaintext.

    We use GnuPG for now. Support for X.509 and other options might
    appear in the future.
    """
    def __init__(self, gpg_binary, gpg_home):
        """Initialize the GnuPG instance."""

        self.gpg_binary = gpg_binary
        self.gpg_home = gpg_home
        if not GPG:
            raise TracError(
                _("Unable to load the python-gnupg module. "
                  "Please check and correct your installation."))
        try:
            self.gpg = GPG(gpgbinary=self.gpg_binary, gnupghome=self.gpg_home)
        except ValueError:
            raise TracError(
                _("Missing the crypto binary. Please check and "
                  "set full path with option 'gpg_binary'."))
        else:
            # get list of available public keys once for later use
            self.pub_keys = self.gpg.list_keys()

    def sign(self, content, private_key=None):
        private_key = self._get_private_key(private_key)

        cipher = self.gpg.sign(content, keyid=private_key, passphrase='')
        return str(cipher)

    def encrypt(self, content, pubkeys):
        # always_trust needed for making it work with just any pubkey
        cipher = self.gpg.encrypt(content, pubkeys, always_trust=True)
        return str(cipher)

    def sign_encrypt(self, content, pubkeys, private_key=None):
        private_key = self._get_private_key(private_key)

        # always_trust needed for making it work with just any pubkey
        cipher = self.gpg.encrypt(content,
                                  pubkeys,
                                  always_trust=True,
                                  sign=private_key,
                                  passphrase='')
        return str(cipher)

    def get_pubkey_ids(self, addr):
        """Find public key with UID matching address to encrypt to."""

        pubkey_ids = []
        if self.pub_keys and 'uids' in self.pub_keys[-1] and \
                'fingerprint' in self.pub_keys[-1]:
            # compile pattern before use for better performance
            rcpt_re = re.compile(addr)
            for k in self.pub_keys:
                for uid in k['uids']:
                    match = rcpt_re.search(uid)
                    if match is not None:
                        # check for key expiration
                        if k['expires'] == '':
                            pubkey_ids.append(k['fingerprint'][-16:])
                        elif (time.time() + 60) < float(k['expires']):
                            pubkey_ids.append(k['fingerprint'][-16:])
                        break
        return pubkey_ids

    def _get_private_key(self, privkey=None):
        """Find private (secret) key to sign with."""

        # read private keys from keyring
        privkeys = self.gpg.list_keys(True)  # True => private keys
        if privkeys > 0 and 'fingerprint' in privkeys[-1]:
            fingerprints = []
            for k in privkeys:
                fingerprints.append(k['fingerprint'])
        else:
            # no private key in keyring
            return None

        if privkey:
            # check for existence of private key received as argument
            # DEVEL: check for expiration as well
            if 7 < len(privkey) <= 40:
                for fp in fingerprints:
                    if fp.endswith(privkey):
                        # work with last 16 significant chars internally,
                        # even if only 8 are required in trac.ini
                        privkey = fp[-16:]
                        break
                # no fingerprint matching key ID
                else:
                    privkey = None
            else:
                # reset invalid key ID
                privkey = None
        else:
            # select (last) private key from keyring
            privkey = fingerprints[-1][-16:]

        return privkey
예제 #27
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))
예제 #28
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)
예제 #29
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))
예제 #30
0
class GpgSandbox:
    """
    The GPG sandbox wraps a :class:`gnupg.GPG` instance that uses a temporary directory as its home directory. This
    allows to import keys without messing with the user's system. It automatically imports files named `*.key` placed
    in `keys_dir` (`data/keys`) by default. The keys can then be referenced by their filename minus the `.key`
    extension, for example `john.doe.key` can then be used with `gpg.get_key('john.doe').
    """
    def __init__(self, tmpdir: str, keys_dir: str = 'data/keys') -> None:
        # GPG needs the homedir to have limited permissions
        os.chmod(tmpdir, stat.S_IRUSR | stat.S_IWUSR | stat.S_IXUSR)

        self.homedir = tmpdir
        self.gpg = GPG(gnupghome=tmpdir)
        self.keys = self.import_keys(keys_dir)

    def get_key_files(self, keys_dir: str) -> Iterable[str]:
        """
        Return the list of key files in the keys directory.
        """
        return glob.glob(
            os.path.join(os.path.dirname(__file__), '..', keys_dir, '*.key'))

    def import_key(self, key: str) -> str:
        """
        Import the given armored key and return its fingerprint.
        """
        import_result = self.gpg.import_keys(key)

        return import_result.fingerprints[0]

    def import_keys(self, keys_dir: str) -> Dict[str, Tuple[str, str]]:
        """
        Iterate over the `.key` files in `keys_dir` and import then into GPG.
        """
        keys = {}

        for key_path in self.get_key_files(keys_dir):
            username = os.path.basename(key_path)[:-len('.key')]

            with open(key_path) as key_file:
                key = key_file.read()

            keys[username] = (self.import_key(key), key)

        return keys

    def encrypt(self, data: str, username: str) -> str:
        """
        Return `data` encrypted for `username`, which should match a key in the keys directory.
        """
        return str(
            self.gpg.encrypt(data, self.keys[username][0], always_trust=True))

    def decrypt(self, data: str) -> str:
        """
        Return `data` decrypted. A corresponding private key must be available so this data can be decrypted.
        """
        return str(self.gpg.decrypt(data, always_trust=True))

    def get_fingerprint(self, username: str) -> str:
        """
        Return the key fingerprint of the given username.
        """
        return self.keys[username][0]

    def get_key(self, username: str) -> str:
        """
        Return the armored key of the given username.
        """
        return self.keys[username][1]
예제 #31
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))
예제 #32
0
gpg = GPG(binary='/usr/bin/gpg2',
          homedir='~/.gnupg',
          keyring='pubring.gpg',
          secring='secring.gpg')

stored_keys = gpg.list_keys()

message = "This is a test message to be encripted."

options_enc = {
    'passphrase': passphrase,
    'armor': True,
    'default_key': gpg_test_fingerprint
    }
encrypted_msg = gpg.encrypt(message, gpg_test_fingerprint, **options_enc)

print(encrypted_msg)

options_dec = {
    'passphrase': passphrase
    }
decrypted_msg = gpg.decrypt(str(encrypted_msg), **options_dec)

assert message == str(decrypted_msg)

print("This is the original message:", decrypted_msg)

''' "Valid" will return a boolean saying whether the decrypted message's
signature is valid.'''
assert decrypted_msg.valid
예제 #33
0
    getCoreLogger().exception("GPG not working: "+str(e))
    sys.exit(1)
    
db_file = os.path.join(get_settings().get_main_config_dir(),"lunchinator.sq3")
tries = 10
public_key = "0x17F57DC2"

cnx = sqlite3.connect(db_file) 
cursor = cnx.cursor()
p,e,c,ce,ec,s,sc,es,esc,cnt = (0,)*10
cursor.execute("select mtype || \" \" || message from statistics_messages where mtype='HELO_INFO' order by rtime desc limit %d"%tries)
tries = 0
for (rec,) in cursor:
    plain_text = rec.encode("utf8")
    
    enc_data = str(gpg.encrypt(plain_text, public_key, always_trust=True))
    enc_data_comp = zlib.compress(enc_data)
    
    comp_data = zlib.compress(plain_text)
    comp_data_enc = str(gpg.encrypt(comp_data, public_key, always_trust=True))
    
    sign_data = str(gpg.sign(plain_text))
    sign_data_comp = zlib.compress(sign_data)
        
    sign_enc_data = str(gpg.encrypt(plain_text, public_key, sign=public_key, always_trust=True))
    sign_enc_data_comp = zlib.compress(sign_enc_data)
    
    p+=len(plain_text)
    e+=len(enc_data)
    c+=len(comp_data)
    ce+=len(comp_data_enc)
예제 #34
0
파일: pyaxo.py 프로젝트: ghtdak/pyaxo
class Axolotl:
    def __init__(self, name, dbname='axolotl.db', dbpassphrase='',
                 user_pathstring='~'):
        self.ratchetKey = None
        self.ratchetPKey = None
        self.name = name
        self.db = None
        self.mode = None
        self.staged_HK_mk = None
        self.state = None
        self.handshakeKey = None
        self.handshakePKey = None
        self.storeTime = None

        user_path = os.path.expanduser(user_pathstring)
        keyring = [user_path + '/.gnupg/pubring.gpg']
        secret_keyring = [user_path + '/.gnupg/secring.gpg']

        self.dbname = user_path + '/tmp/pyaxo_db/' + dbname

        self.gpg = GPG(gnupghome=user_path + '/.axolotl', gpgbinary='gpg',
                       keyring=keyring,
                       secret_keyring=secret_keyring,
                       options=['--throw-keyids',
                                '--personal-digest-preferences=sha256',
                                '--s2k-digest-algo=sha256'])
        self.gpg.encoding = 'utf-8'

        if dbpassphrase != '' or dbpassphrase is None:
            self.dbpassphrase = dbpassphrase
        else:
            self.dbpassphrase = getpass(
                'Database passphrase for ' + self.name + ': ').strip()

        self.db_init()

    def db_init(self):

        try:
            self.db = self.open_db()
        except sqlite3.OperationalError:
            raise (Axolotl_exception('Bad sql! Password problem - \
            cannot create the database.'))

        self.mode = None
        self.staged_HK_mk = {}

        self.state = {}
        self.state['DHIs_priv'], self.state['DHIs'] = self.genKey()
        self.state['DHRs_priv'], self.state['DHRs'] = self.genKey()

        self.handshakeKey, self.handshakePKey = self.genKey()

        # minimum time (seconds) to store missed ephemeral message keys
        self.storeTime = 2 * 86400
        with self.db:
            cur = self.db.cursor()

            cur.execute("""
            CREATE TABLE IF NOT EXISTS skipped_mk
            (my_identity, to_identity, HKr TEXT, mk TEXT,
              timestamp INTEGER )""")

            cur.execute("""
            CREATE UNIQUE INDEX IF NOT EXISTS
                         message_keys ON skipped_mk (mk)""")

            cur.execute("""
            CREATE TABLE IF NOT EXISTS conversations
            (my_identity TEXT, other_identity TEXT, RK TEXT, HKs TEXT,
              HKr TEXT, NHKs TEXT, NHKr TEXT, CKs TEXT, CKr TEXT,
              DHIs_priv TEXT, DHIs TEXT, DHIr TEXT, DHRs_priv TEXT,
              DHRs TEXT, DHRr TEXT, CONVid TEXT, Ns INTEGER, Nr INTEGER,
              PNs INTEGER, ratchet_flag INTEGER, mode INTEGER)""")

            cur.execute("""
            CREATE UNIQUE INDEX IF NOT EXISTS
                         conversation_route ON
                         conversations (my_identity, other_identity)""")
        self.commit_skipped_mk()

    def triple_dh(self, a, a0, B, B0):
        if self.mode is None:
            raise (Axolotl_exception('Mode must be set'))
        if self.mode:
            return sha256(
                self.gen_dh(a, B0) + self.gen_dh(a0, B) +
                self.gen_dh(a0, B0)).digest()
        else:
            return sha256(
                self.gen_dh(a0, B) + self.gen_dh(a, B0) +
                self.gen_dh(a0, B0)).digest()

    def initState(self, other_name, other_identityKey, other_handshakeKey,
                  other_ratchetKey, verify=True):
        if verify:
            print('Confirm ' + other_name + ' has identity key fingerprint:\n')
            fingerprint = sha224(other_identityKey).hexdigest().upper()
            fprint = ''
            for i in range(0, len(fingerprint), 4):
                fprint += fingerprint[i:i + 2] + ':'
            print(fprint[:-1] + '\n')
            print('Be sure to verify this fingerprint with ' + other_name +
                  ' by some out-of-band method!')
            print('Otherwise, you may be subject to a \
            Man-in-the-middle attack!\n')
            ans = raw_input('Confirm? y/N: ').strip()
            if ans != 'y':
                raise (Axolotl_exception('Key fingerprint \
                not confirmed - exception'))

        if self.state['DHIs'] < other_identityKey:
            self.mode = True
        else:
            self.mode = False
        mkey = self.triple_dh(self.state['DHIs_priv'], self.handshakeKey,
                              other_identityKey, other_handshakeKey)

        self.createState(other_name, mkey,
                         mode=self.mode,
                         other_identityKey=other_identityKey,
                         other_ratchetKey=other_ratchetKey)

    def createState(self, other_name, mkey, mode=None, other_identityKey=None,
                    other_ratchetKey=None):
        self.mode = mode

        if self.mode is None:  # mode not selected
            raise (Axolotl_exception('Mode must be set'))
        if self.mode:  # alice mode
            RK = pbkdf2(mkey, b'\x00', 10, prf='hmac-sha256')
            HKs = None
            HKr = pbkdf2(mkey, b'\x02', 10, prf='hmac-sha256')
            NHKs = pbkdf2(mkey, b'\x03', 10, prf='hmac-sha256')
            NHKr = pbkdf2(mkey, b'\x04', 10, prf='hmac-sha256')
            CKs = None
            CKr = pbkdf2(mkey, b'\x06', 10, prf='hmac-sha256')
            DHRs_priv = None
            DHRs = None
            DHRr = other_ratchetKey
            CONVid = pbkdf2(mkey, b'\x07', 10, prf='hmac-sha256')
            Ns = 0
            Nr = 0
            PNs = 0
            ratchet_flag = True
        else:  # bob mode
            RK = pbkdf2(mkey, b'\x00', 10, prf='hmac-sha256')
            HKs = pbkdf2(mkey, b'\x02', 10, prf='hmac-sha256')
            HKr = None
            NHKs = pbkdf2(mkey, b'\x04', 10, prf='hmac-sha256')
            NHKr = pbkdf2(mkey, b'\x03', 10, prf='hmac-sha256')
            CKs = pbkdf2(mkey, b'\x06', 10, prf='hmac-sha256')
            CKr = None
            DHRs_priv = self.state['DHRs_priv']
            DHRs = self.state['DHRs']
            DHRr = None
            CONVid = pbkdf2(mkey, b'\x07', 10, prf='hmac-sha256')
            Ns = 0
            Nr = 0
            PNs = 0
            ratchet_flag = False
        DHIr = other_identityKey

        self.state = \
            {'name': self.name, 'other_name': other_name, 'RK': RK,
             'HKs': HKs, 'HKr': HKr, 'NHKs': NHKs, 'NHKr': NHKr, 'CKs': CKs,
             'CKr': CKr, 'DHIs_priv': self.state['DHIs_priv'],
             'DHIs': self.state['DHIs'], 'DHIr': DHIr,
             'DHRs_priv': DHRs_priv, 'DHRs': DHRs, 'DHRr': DHRr,
             'CONVid': CONVid, 'Ns': Ns, 'Nr': Nr, 'PNs': PNs,
             'ratchet_flag': ratchet_flag,
             }

        self.ratchetKey = False
        self.ratchetPKey = False

    def encrypt(self, plaintext):
        if self.state['ratchet_flag']:
            self.state['DHRs_priv'], self.state['DHRs'] = self.genKey()
            self.state['HKs'] = self.state['NHKs']
            self.state['RK'] = sha256(self.state['RK'] +
                                      self.gen_dh(
                                          self.state['DHRs_priv'],
                                          self.state['DHRr'])).digest()
            if self.mode:
                self.state['NHKs'] = pbkdf2(self.state['RK'], b'\x03', 10,
                                            prf='hmac-sha256')
                self.state['CKs'] = pbkdf2(self.state['RK'], b'\x05', 10,
                                           prf='hmac-sha256')
            else:
                self.state['NHKs'] = pbkdf2(self.state['RK'], b'\x04', 10,
                                            prf='hmac-sha256')
                self.state['CKs'] = pbkdf2(self.state['RK'], b'\x06', 10,
                                           prf='hmac-sha256')
            self.state['PNs'] = self.state['Ns']
            self.state['Ns'] = 0
            self.state['ratchet_flag'] = False
        mk = sha256(self.state['CKs'] + '0').digest()
        msg1 = self.enc(self.state['HKs'], str(self.state['Ns']).zfill(3) +
                        str(self.state['PNs']).zfill(3) + self.state['DHRs'])
        msg2 = self.enc(mk, plaintext)
        pad_length = 106 - len(msg1)
        pad = os.urandom(pad_length - 1) + chr(pad_length)
        msg = msg1 + pad + msg2
        self.state['Ns'] += 1
        self.state['CKs'] = sha256(self.state['CKs'] + '1').digest()
        return msg

    def commit_skipped_mk(self):
        timestamp = int(time())
        with self.db:
            cur = self.db.cursor()
            for mk, HKr in self.staged_HK_mk.iteritems():
                cur.execute("""REPLACE INTO skipped_mk (my_identity,
                  to_identity, HKr, mk, timestamp ) VALUES (?, ?, ?, ?, ?)""",
                            self.state['name'],
                            self.state['other_name'],
                            b2a_base64(HKr).strip(),
                            b2a_base64(mk).strip(),
                            timestamp)

            rowtime = timestamp - self.storeTime
            cur.execute('DELETE FROM skipped_mk WHERE timestamp < ?',
                        (rowtime,))

    def trySkippedMK(self, msg, pad_length, name, other_name):
        with self.db:
            cur = self.db.cursor()
            cur.execute('SELECT * FROM skipped_mk')
            rows = cur.fetchall()
            for row in rows:
                if name == row[0] and other_name == row[1]:
                    msg1 = msg[:106 - pad_length]
                    msg2 = msg[106:]
                    header = self.dec(a2b_base64(row[2]), msg1)
                    body = self.dec(a2b_base64(row[3]), msg2)
                    if header != '' and body != '':
                        cur.execute('DELETE FROM skipped_mk WHERE mk = ?',
                                    (row[3],))
                        return body
        return False

    def stageSkippedMK(self, HKr, Nr, Np, CKr):
        CKp = CKr
        for i in range(Np - Nr):
            mk = sha256(CKp + '0').digest()
            CKp = sha256(CKp + '1').digest()
            self.staged_HK_mk[mk] = HKr

        mk = sha256(CKp + '0').digest()
        CKp = sha256(CKp + '1').digest()
        return CKp, mk

    def decrypt(self, msg):
        pad = msg[105:106]
        pad_length = ord(pad)
        msg1 = msg[:106 - pad_length]

        body = self.trySkippedMK(msg, pad_length, self.state['name'],
                                 self.state['other_name'])
        if body and body != '':
            return body

        header = None
        if self.state['HKr']:
            header = self.dec(self.state['HKr'], msg1)
        if header and header != '':
            Np = int(header[:3])
            CKp, mk = self.stageSkippedMK(self.state['HKr'], self.state['Nr'],
                                          Np, self.state['CKr'])
            body = self.dec(mk, msg[106:])
            if not body or body == '':
                raise (Axolotl_exception('Undecipherable message'))
        else:
            header = self.dec(self.state['NHKr'], msg1)
            if self.state['ratchet_flag'] or not header or header == '':
                raise (Axolotl_exception('Undecipherable message'))

            Np = int(header[:3])
            PNp = int(header[3:6])
            DHRp = header[6:]
            if self.state['CKr']:
                self.stageSkippedMK(self.state['HKr'], self.state['Nr'], PNp,
                                    self.state['CKr'])
            HKp = self.state['NHKr']
            RKp = sha256(
                self.state['RK'] + self.gen_dh(self.state['DHRs_priv'],
                                               DHRp)).digest()
            if self.mode:
                NHKp = pbkdf2(RKp, b'\x04', 10, prf='hmac-sha256')
                CKp = pbkdf2(RKp, b'\x06', 10, prf='hmac-sha256')
            else:
                NHKp = pbkdf2(RKp, b'\x03', 10, prf='hmac-sha256')
                CKp = pbkdf2(RKp, b'\x05', 10, prf='hmac-sha256')
            CKp, mk = self.stageSkippedMK(HKp, 0, Np, CKp)
            body = self.dec(mk, msg[106:])
            if not body or body == '':
                raise (Axolotl_exception('Undecipherable message'))

            self.state['RK'] = RKp
            self.state['HKr'] = HKp
            self.state['NHKr'] = NHKp
            self.state['DHRr'] = DHRp
            self.state['DHRs_priv'] = None
            self.state['DHRs'] = None
            self.state['ratchet_flag'] = True
        self.commit_skipped_mk()
        self.state['Nr'] = Np + 1
        self.state['CKr'] = CKp
        return body

    def encrypt_file(self, filename):
        with open(filename, 'r') as f:
            plaintext = f.read()
        ciphertext = b2a_base64(self.encrypt(plaintext))
        with open(filename + '.asc', 'w') as f:
            lines = [ciphertext[i:i + 64] for i in
                     xrange(0, len(ciphertext), 64)]
            for line in lines:
                f.write(line + '\n')

    def decrypt_file(self, filename):
        with open(filename, 'r') as f:
            ciphertext = a2b_base64(f.read())
        plaintext = self.decrypt(ciphertext)
        print(plaintext)

    def encrypt_pipe(self):
        plaintext = sys.stdin.read()
        ciphertext = b2a_base64(self.encrypt(plaintext))
        sys.stdout.write(ciphertext)
        sys.stdout.flush()

    def decrypt_pipe(self):
        ciphertext = a2b_base64(sys.stdin.read())
        plaintext = self.decrypt(ciphertext)
        sys.stdout.write(plaintext)
        sys.stdout.flush()

    def printKeys(self):
        print('Your Identity key is:\n' + b2a_base64(
            self.state['DHIs']))
        fingerprint = sha224(self.state['DHIs']).hexdigest().upper()
        fprint = ''
        for i in range(0, len(fingerprint), 4):
            fprint += fingerprint[i:i + 2] + ':'
        print('Your identity key fingerprint is: ')
        print(fprint[:-1] + '\n')
        print('Your Ratchet key is:\n' + b2a_base64(
            self.state['DHRs']))
        if self.handshakeKey:
            print('Your Handshake key is:\n' + b2a_base64(
                self.handshakePKey))
        else:
            print('Your Handshake key is not available')

    def to_json(self):
        _j = {'name': self.name,
              'identity_key': b2a_base64(self.state('DHIs')),
              'fingerprint': sha224(self.state['DHIs']).hexdigest().upper(),
              'ratchet_key': b2a_base64(self.state['DHRs'])}
        return json.dumps(_j)

    def init_from_json(self, _jsn):
        _k = json.loads(_jsn)
        self.initState(_k['name'], a2b_base64(_k['identity_key']),
                       a2b_base64(_k['fingerprint']),
                       a2b_base64(_k['ratchet_key']))
        self.saveState()

    def saveState(self):
        ktup = ('HKs', 'HKr', 'CKs', 'CKR', 'DHIr', 'DHRs_priv', 'DHRs')

        v = {k: b2a_base64(self.state[k]).strip for k in ktup}

        ratchet_flag = 1 if self.state['ratchet_flag'] else 0
        mode = 1 if self.mode else 0
        with self.db:
            cur = self.db.cursor()
            cur.execute("""\
            REPLACE INTO conversations (
                       my_identity, other_identity, RK,HKS, HKr, NHKs, NHKr,
                       CKs, CKr, DHIs_priv, DHIs, DHIr, DHRs_priv, DHRs,
                       DHRr, CONVid, Ns, Nr, PNs, ratchet_flag, mode)
                       VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?,
                       ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)""",
                        (self.state['name'],
                         self.state['other_name'],
                         b2a_base64(self.state['RK']).strip(),
                         v['HKs'], v['HKr'],
                         b2a_base64(self.state['NHKs']).strip(),
                         b2a_base64(self.state['NHKr']).strip(),
                         v['CKs'], v['CKr'],
                         b2a_base64(self.state['DHIs_priv']).strip(),
                         b2a_base64(self.state['DHIs']).strip(),
                         v['DHIr'], v['DHRs_priv'], v['DHRs'], v['DHRr'],
                         b2a_base64(self.state['CONVid']).strip(),
                         self.state['Ns'], self.state['Nr'], self.state['PNs'],
                         ratchet_flag,
                         mode
                         ))
        self.write_db()

    def loadState(self, name, other_name):
        self.db = self.open_db()
        with self.db:
            cur = self.db.cursor()
            try:
                cur.execute('SELECT * FROM conversations')
            except sqlite3.OperationalError:
                raise (Axolotl_exception('Bad sql! Password problem - \
                cannot loadState()'))

            rows = cur.fetchall()
            for row in rows:
                if row[0] == name and row[1] == other_name:
                    self.state = {'name': row[0],
                                  'other_name': row[1],
                                  'RK': a2b_base64(row[2]),
                                  'NHKs': a2b_base64(row[5]),
                                  'NHKr': a2b_base64(row[6]),
                                  'DHIs_priv': a2b_base64(row[9]),
                                  'DHIs': a2b_base64(row[10]),
                                  'CONVid': a2b_base64(row[15]),
                                  'Ns': row[16],
                                  'Nr': row[17],
                                  'PNs': row[18]}

                    self.name = self.state['name']

                    def do_bin(loc):
                        if row[loc] == '0':
                            return None
                        else:
                            return a2b_base64(row[loc])

                    self.state['HKs'] = do_bin(3)
                    self.state['HKr'] = do_bin(4)
                    self.state['CKs'] = do_bin(7)
                    self.state['CKr'] = do_bin(8)
                    self.state['DHIr'] = do_bin(11)
                    self.state['DHRs_priv'] = do_bin(12)
                    self.state['DHRs'] = do_bin(13)
                    self.state['DHRr'] = do_bin(14)

                    ratchet_flag = row[19]
                    if ratchet_flag == 1:
                        self.state['ratchet_flag'] = True
                    else:
                        self.state['ratchet_flag'] = False

                    mode = row[20]
                    self.mode = True if mode == 1 else False
                    return  # exit at first match
            return False  # if no matches

    def open_db(self):

        db = sqlite3.connect(':memory:')

        try:
            with open(self.dbname, 'rb') as f:
                if self.dbpassphrase is not None:
                    sql = \
                        self.gpg.decrypt_file(f, passphrase=self.dbpassphrase)

                    if sql is not None and sql != '':
                        db.cursor().executescript(sql.data)
                        return db
                    else:
                        raise (Axolotl_exception('Bad passphrase!'))
                else:
                    sql = f.read()
                    db.cursor().executescript(sql)
                    return db
        except IOError:
            return db

    def write_db(self):

        sql = ''
        for item in self.db.iterdump():
            sql = sql + item + '\n'
        if self.dbpassphrase is not None:
            crypt_sql = self.gpg.encrypt(sql, recipients=None,
                                         symmetric='AES256',
                                         armor=False,
                                         always_trust=True,
                                         passphrase=self.dbpassphrase)

            with open(self.dbname, 'wb') as f:
                f.write(crypt_sql.data)
        else:
            with open(self.dbname, 'w') as f:
                f.write(sql)

    def print_state(self):

        print('\nWarning: saving this data to disk is insecure!\n')

        for key in sorted(self.state):
            if 'priv' in key:
                pass
            else:
                if self.state[key] is None:
                    print(key + ': None')
                elif type(self.state[key]) is bool:
                    if self.state[key]:
                        print(key + ': True')
                    else:
                        print(key + ': False')
                elif type(self.state[key]) is str:
                    try:
                        self.state[key].decode('ascii')
                        print(key + ': ' + self.state[key])
                    except UnicodeDecodeError:
                        print(key + ': ' + b2a_base64(
                            self.state[key]).strip())
                else:
                    print(key + ': ' + str(self.state[key]))
        if self.mode:
            print('Mode: Alice')
        else:
            print('Mode: Bob')

    @staticmethod
    def genKey():
        key = keys.Private()
        privkey = key.private
        pubkey = key.get_public().serialize()
        return privkey, pubkey

    @staticmethod
    def gen_dh(a, B):
        key = keys.Private(secret=a)
        return key.get_shared_key(keys.Public(B))

    def dec(self, key, encrypted):
        key = hexlify(key)
        msg = self.gpg.decrypt(GPG_HEADER + encrypted,
                               passphrase=key, always_trust=True)
        return msg.data

    def enc(self, key, plaintext):
        key = hexlify(key)
        msg = self.gpg.encrypt(plaintext, recipients=None,
                               symmetric=GPG_CIPHER,
                               armor=False,
                               always_trust=True, passphrase=key)
        return msg.data[6:]
예제 #35
0
def encrypt(data: str, fingerprint: str, gpg: GPG) -> str:
    """
    Encrypt data for the given `fingerprint`. The key must be imported in the GPG keys directory first.
    """
    return str(gpg.encrypt(data, fingerprint, always_trust=True))
예제 #36
0
    args = parser.parse_args()

    gpg_home, pass_loc = get_env_vars()
    gpg = GPG(gnupghome=gpg_home)
    with open(pass_loc, mode='rb') as f:
        decoded = gpg.decrypt_file(f, passphrase=getpass())
    if decoded.data == b'':
        print("Incorrect Passphrase")
        exit()
    passes = loads(clean_gpg_json(decoded.data))

    if args.list:
        for key in passes.keys(): print(key)
    if args.key is not None:
        if args.password:
            print_pass(passes, args.key)
        if args.user:
            print_user(passes, args.key)
    if args.set or args.remove:
        keys = gpg.list_keys()
        for index, key in enumerate(keys):
            print(index, key['uids'])
        fp = keys[int(input('Pick gpg key: '))]['fingerprint']
        key = input('Specify key: ')
        if args.set:
            passes[key] = getpass()
        else:
            del passes[key]
        with open(pass_loc, 'wb') as f:
            f.write(gpg.encrypt(dumps(passes), fp).data)
예제 #37
0
def vote(request, poll_id):
    if not request.user.is_authenticated():
        return HttpResponseRedirect('/')
    else:
        logged_in = True

    error = ''
    success = ''
    try:
        poll = Poll.objects.get(pk=poll_id)
    except Poll.DoesNotExist:
        raise Http404

    username = request.user.username
    if (not poll.is_allowed_voter(username)) \
      or poll.has_voted(username) \
      or (poll.starts > datetime.datetime.now()) \
      or (poll.ends < datetime.datetime.now()):
        return HttpResponseRedirect('/mypolls')

    poll_choices = Choice.objects.filter(poll=poll).order_by('id')
    choice_type = "radio"
    if poll.max_choices > 1:
        choice_type = "checkbox"

    vote_tag = ''
    vote_receipt_encrypted = ''

    if request.POST:
        form = Form(request.POST)
        if form.is_valid():
            choices = request.POST.getlist('choices')

            # Check that the submitted choices exist and belong to the poll
            for choice in choices:
                try:
                    c = Choice.objects.get(pk=choice, poll=poll)
                except Choice.DoesNotExist:
                    error = "The submitted choices are not valid choices of the poll"

            # Check that the submitted choices are between min and max number of choices allowed for the poll
            if len(choices) > poll.max_choices:
                error = 'You cannot vote for more than ' + str(
                    poll.max_choices) + ' choices'
            if len(choices) < poll.min_choices:
                error = 'You must vote for at least ' + str(
                    poll.min_choices) + ' choices'
                if poll.max_choices == 1:  # a better error message for single choice polls
                    error = 'You must select a choice'
            if list_has_duplicates(choices):
                error = 'Each choice can be selected only once'

            if not error:
                # Construct a unique, random string to use as a vote tag
                while not vote_tag:
                    vote_tag = ''.join(
                        random.choice(string.ascii_uppercase + string.digits)
                        for x in range(35))
                    try:
                        v = Vote.objects.get(tag=vote_tag)
                        vote_tag = ''
                    except Vote.DoesNotExist:  # our random string is unique so we can use it as a vote tag
                        # Encrypt the vote tag with user's public pgp key and sign it with the key of the system authority
                        gpg = GPG(gpgbinary=settings.GNUPGBINARY,
                                  gnupghome=settings.GNUPGHOME)
                        vote_receipt = """GPGVote: Vote Receipt
---------------------

You are voter: 
  %s

You voted for Poll:
  \'%s\'

Created by: 
  %s

Your Vote Tag is: %s
  
You made the following choices:"""  % (request.user.pgpkey.name + ' <' + request.user.username + '>', poll.question, \
                                                          poll.creator.pgpkey.name + ' <' + poll.creator.username + '>', vote_tag)

                        for choice in choices:
                            choice = Choice.objects.get(pk=choice, poll=poll)
                            vote_receipt = vote_receipt + '\n  * %s' % choice.choice

                        vote_receipt_encrypted = gpg.encrypt(
                            vote_receipt,
                            request.user.pgpkey.fingerprint,
                            always_trust=True,
                            sign=settings.SYSTEM_KEY_FINGERPRINT,
                            passphrase=settings.SYSTEM_KEY_PASSWD)
                        # Create the actual vote records in database
                        for choice in choices:
                            vote = Vote(choice=Choice.objects.get(id=choice),
                                        tag=vote_tag)
                            vote.save()
                        poll.add_voter(voter=username, To='who_voted')
                        poll.save()

                success = 'You have successfully voted for the poll'

    return render_to_response('vote.html', {
        'user': username,
        'poll': poll,
        'choices': poll_choices,
        'choice_type': choice_type,
        'error': error,
        'success': success,
        'vote_receipt': vote_receipt_encrypted,
        'logged_in': logged_in
    },
                              context_instance=RequestContext(request))