def extract_signers(email, signature_blocks, encryption_name=DEFAULT_CRYPTO):
        ''' Extract the signers if message is signed. '''

        known_signers = False

        crypto = CryptoFactory.get_crypto(encryption_name, crypto_software.get_classname(encryption_name))
        log_message('checking if message signed by {}'.format(email))
        for signature_block in signature_blocks:
            if crypto.verify(signature_block, email):
                signer_dict = {
                    SIGNER: email,
                    SIGNER_VERIFIED: True,
                }
                known_signers = True
                log_message('{} signed message'.format(email))
            else:
                log_message('signature block\n{}'.format(signature_block))
                signer = crypto.get_signer(signature_block)
                log_message('unverified signature by {}'.format(signer))
                signer_dict = {
                    SIGNER: signer,
                    SIGNER_VERIFIED: False,
                }

            crypto_message.add_clear_signer(signer_dict)

        log_message('clear signers: {}'.format(crypto_message.clear_signers_list()))

        return known_signers
    def extract_signers(email,
                        signature_blocks,
                        encryption_name=DEFAULT_CRYPTO):
        ''' Extract the signers if message is signed. '''

        known_signers = False

        crypto = CryptoFactory.get_crypto(
            encryption_name, crypto_software.get_classname(encryption_name))
        log_message('checking if message signed by {}'.format(email))
        for signature_block in signature_blocks:
            if crypto.verify(signature_block, email):
                signer_dict = {
                    SIGNER: email,
                    SIGNER_VERIFIED: True,
                }
                known_signers = True
                log_message('{} signed message'.format(email))
            else:
                log_message('signature block\n{}'.format(signature_block))
                signer = crypto.get_signer(signature_block)
                log_message('unverified signature by {}'.format(signer))
                signer_dict = {
                    SIGNER: signer,
                    SIGNER_VERIFIED: False,
                }

            crypto_message.add_clear_signer(signer_dict)

        log_message('clear signers: {}'.format(
            crypto_message.clear_signers_list()))

        return known_signers
def main(encryption_name):
    '''
        Clear all failed jobs.

        >>> main('GPG')
    '''

    plugin = CryptoFactory.get_crypto(encryption_name)
    plugin.wait_until_queue_empty()
Example #4
0
    def clean(self):
        cleaned_data = super(EncryptionSoftwareForm, self).clean()

        name = cleaned_data.get('name')
        classname = cleaned_data.get('classname')
        crypto = CryptoFactory.get_crypto(name, classname)
        if not crypto or not crypto.is_available():
            error_message = i18n(
                '{encryption} is not available.'.format(encryption=name))
            _log.write(error_message)
            raise ValidationError(error_message)

        return cleaned_data
Example #5
0
    def _clear_sign_message(self, encryption_name):
        '''
            Clear sign the message if From has a key.
        '''
        result_ok = False
        try:
            self._log_message("signing message with {}".format(encryption_name))
            crypto = CryptoFactory.get_crypto(encryption_name, get_classname(encryption_name))
            if crypto is None:
                self._log_message("{} is not ready to use".format(encryption_name))
            elif (self.crypto_message is None or
                  self.crypto_message.smtp_sender() is None):
                self._log_message("missing key data to sign message")
            else:
                # get all the private user ids that have encryption keys
                private_user_ids = crypto.get_private_user_ids()
                if self.DEBUGGING: self._log_message('private user ids: {}'.format(private_user_ids))

                result_ok = self._prep_from_user(private_user_ids, encryption_name)
                if result_ok:

                    from_user_id, passcode, error_message = self._get_from_crypto_details(
                        encryption_name, private_user_ids)

                    result_ok = from_user_id is not None and passcode is not None
                else:
                    self._log_message("private_user_ids is not None and len(private_user_ids) > 0: {}".format(
                        private_user_ids is not None and len(private_user_ids) > 0))

                if result_ok:
                    self._log_message("from user ID: {}".format(from_user_id))
                    self._log_message("subject: {}".format(
                      self.crypto_message.get_email_message().get_header(mime_constants.SUBJECT_KEYWORD)))

                    result_ok = self._clear_sign_message_with_keys(crypto, from_user_id, passcode)
                    self._log_message('signed message: {}'.format(result_ok))

                else:
                    # the message hasn't been signed, but we have
                    # successfully processed it
                    self.crypto_message.set_filtered(True)

        except Exception:
            result_ok = False
            record_exception()
            self._log_message('EXCEPTION - see syr.exception.log for details')

        return result_ok
Example #6
0
def get_public_key_header_name(encryption_name):
    '''
        Get the public key header's name.

        >>> header_name = get_public_key_header_name('GPG')
        >>> header_name == 'X-OpenPGP-PublicKey'
        True
    '''

    if (is_multiple_encryption_active() and
        encryption_name != CryptoFactory.get_default_encryption_name()):
        header_name = '{}-{}'.format(constants.PUBLIC_KEY_HEADER, encryption_name)
    else:
        header_name = constants.PUBLIC_KEY_HEADER

    return header_name
Example #7
0
    def _decrypt_message_with_crypto(self, encryption_name):
        '''
            Decrypt a message using the encryption software (internal use only).
        '''

        decrypted = False
        self.log_message("encryption program: {}".format(encryption_name))

        from_user = self.crypto_message.smtp_sender()
        to_user = self.crypto_message.smtp_recipient()

        passcode = user_keys.get_passcode(to_user, encryption_name)
        if passcode == None or len(passcode) <= 0:
            tag = '{email} does not have a private key configured.'.format(email=to_user)
            self.log_message(tag)
            self.crypto_message.add_error_tag_once(tag)
        else:
            # make sure that the key for the recipient is ok; if it's not, a CryptoException is thrown
            __, verified, __ = contacts.is_key_ok(to_user, encryption_name)
            self.log_message('{} {} key pinned'.format(to_user, encryption_name))
            self.log_message('{} {} key verified: {}'.format(to_user, encryption_name, verified))

            crypto = CryptoFactory.get_crypto(encryption_name, crypto_software.get_classname(encryption_name))

            # try to verify signature in case it was clear signed after it was encrypted
            decrypt_utils.verify_clear_signed(
               from_user, self.crypto_message, encryption_name=crypto.get_name(), crypto=crypto)

            self.log_message('trying to decrypt using {} private {} key.'.format(to_user, encryption_name))
            if is_open_pgp_mime(self.crypto_message.get_email_message().get_message()):
                decrypted = self._decrypt_open_pgp_mime(from_user, crypto, passcode)
            else:
                decrypted = self._decrypt_inline_pgp(from_user, crypto, passcode)
            self.log_message('decrypted using {} private {} key: {}'.format(to_user, encryption_name, decrypted))

            # try to verify signature in case it was clear signed before it was encrypted
            if decrypted:
                decrypt_utils.verify_clear_signed(
                   from_user, self.crypto_message, encryption_name=crypto.get_name(), crypto=crypto)

                if self.DEBUGGING:
                    self.log_message('decrypted message:\n{}'.format(
                        self.crypto_message.get_email_message().get_message()))
                    self.log_message('decrypted message char set: {}'.format(get_charset(self.crypto_message.get_email_message())))

        return decrypted
    def encrypt_message(crypto_message, data):

        encryption_ready = False
        encrypted_with = []

        # use the metadata address' encryption
        to_metadata_address = metadata.get_metadata_address(email=to_user)
        encryption_names = contacts.get_encryption_names(to_metadata_address)
        log_message('{} encryption software for: {}'.format(
            encryption_names, to_metadata_address))

        if len(encryption_names) < 1:
            error_message = i18n(
                'Unable to protect metadata because there are no encryption programs for {}.'
                .format(to_metadata_address))
            log_message(error_message)
            raise MessageException(value=error_message)
        else:
            # encrypt with each common encryption program
            for encryption_name in encryption_names:
                ready, to_metadata_address, __ = metadata.get_metadata_user_details(
                    to_user, encryption_name)
                log_message('to metadata ready {} '.format(ready))

                if ready:
                    ready, from_metadata_address, passcode = metadata.get_from_metadata_user_details(
                        from_user, encryption_name)
                    log_message('metadata keys ready {}'.format(ready))

                if ready:
                    log_message(
                        'protecting metadata with {}'.format(encryption_names))

                    # if we're ready with any key, then the encryption is ready
                    encryption_ready = True

                    from_user_id = get_email(from_metadata_address)
                    to_user_id = get_email(to_metadata_address)
                    crypto_message.set_smtp_sender(from_user_id)
                    crypto_message.set_smtp_recipient(to_user_id)

                    # use the default charset to prevent metadata leakage
                    charset, __ = get_charset(constants.DEFAULT_CHAR_SET)
                    users_dict = {
                        TO_KEYWORD: to_user_id,
                        FROM_KEYWORD: from_user_id,
                        PASSCODE_KEYWORD: passcode,
                        CHARSET_KEYWORD: charset
                    }

                    crypto = CryptoFactory.get_crypto(
                        encryption_name, get_classname(encryption_name))
                    ciphertext, error_message = encrypt_byte_array(
                        data, crypto, users_dict)
                    if ciphertext is not None and len(ciphertext) > 0:
                        crypto_message.get_email_message().get_message(
                        ).set_payload(ciphertext)

                        crypto_message.add_public_key_to_header(
                            users_dict[FROM_KEYWORD])
                        set_sigs(crypto_message, from_user_id, passcode)
                        crypto_message.set_filtered(True)
                        crypto_message.set_crypted(True)

                        # use the encrypted data for the next level of encryption
                        data = ciphertext

                        encrypted_with.append(encryption_name)
                    else:
                        log_message(
                            'unable to encrypt the metadata with {}'.format(
                                encryption_name))
                        raise MessageException(value=error_message)
                else:
                    log_message('unable to protect metadata with {}'.format(
                        encryption_name))

            return encryption_ready, encrypted_with
Example #9
0
    def _decrypt_message_with_crypto(self, encryption_name):
        '''
            Decrypt a message using the encryption software (internal use only).
        '''

        decrypted = False
        self.log_message("encryption program: {}".format(encryption_name))

        from_user = self.crypto_message.smtp_sender()
        to_user = self.crypto_message.smtp_recipient()

        passcode = user_keys.get_passcode(to_user, encryption_name)
        if passcode == None or len(passcode) <= 0:
            tag = '{email} does not have a private key configured.'.format(
                email=to_user)
            self.log_message(tag)
            self.crypto_message.add_error_tag_once(tag)
        else:
            # make sure that the key for the recipient is ok; if it's not, a CryptoException is thrown
            __, verified, __ = contacts.is_key_ok(to_user, encryption_name)
            self.log_message('{} {} key pinned'.format(to_user,
                                                       encryption_name))
            self.log_message('{} {} key verified: {}'.format(
                to_user, encryption_name, verified))

            crypto = CryptoFactory.get_crypto(
                encryption_name,
                crypto_software.get_classname(encryption_name))

            # try to verify signature in case it was clear signed after it was encrypted
            decrypt_utils.verify_clear_signed(
                from_user,
                self.crypto_message,
                encryption_name=crypto.get_name(),
                crypto=crypto)

            self.log_message(
                'trying to decrypt using {} private {} key.'.format(
                    to_user, encryption_name))
            if is_open_pgp_mime(
                    self.crypto_message.get_email_message().get_message()):
                decrypted = self._decrypt_open_pgp_mime(
                    from_user, crypto, passcode)
            else:
                decrypted = self._decrypt_inline_pgp(from_user, crypto,
                                                     passcode)
            self.log_message('decrypted using {} private {} key: {}'.format(
                to_user, encryption_name, decrypted))

            # try to verify signature in case it was clear signed before it was encrypted
            if decrypted:
                decrypt_utils.verify_clear_signed(
                    from_user,
                    self.crypto_message,
                    encryption_name=crypto.get_name(),
                    crypto=crypto)

                if self.DEBUGGING:
                    self.log_message('decrypted message:\n{}'.format(
                        self.crypto_message.get_email_message().get_message()))
                    self.log_message('decrypted message char set: {}'.format(
                        get_charset(self.crypto_message.get_email_message())))

        return decrypted
Example #10
0
    def _encrypt_message(self, encryption_name):
        '''
            Encrypt the message if both To and From have keys.

            Otherwise, if we just have a key for the From, then add it to the header.
        '''
        result_ok = False
        try:
            self._log_message("encrypting message with {}".format(encryption_name))
            crypto = CryptoFactory.get_crypto(encryption_name, get_classname(encryption_name))
            if crypto is None:
                self._log_message("{} is not ready to use".format(encryption_name))
            elif (self.crypto_message is None or
                  self.crypto_message.smtp_sender() is None or
                  self.crypto_message.smtp_recipient() is None):
                self._log_message("missing key data to encrypt message")
            else:
                # get all the user ids that have encryption keys
                user_ids = crypto.get_user_ids()
                if self.DEBUGGING: self._log_message('user ids: {}'.format(user_ids))
                private_user_ids = crypto.get_private_user_ids()
                if self.DEBUGGING: self._log_message('private user ids: {}'.format(private_user_ids))

                self._prep_from_user(private_user_ids, encryption_name)
                users_dict, result_ok = self._get_crypto_details(encryption_name, user_ids)
                if result_ok or options.create_private_keys():

                    # regardless if we can encrypt this message,
                    # add From's public key if we have it and we're exchanging keys
                    if options.auto_exchange_keys() and users_dict[encrypt_utils.FROM_KEYWORD] is not None:
                        self.crypto_message.add_public_key_to_header(users_dict[encrypt_utils.FROM_KEYWORD])
                else:
                    self._log_message("user_ids is not None and len(user_ids) > 0: {}".format(
                        user_ids is not None and len(user_ids) > 0))

                if result_ok:
                    self._log_message("from user ID: {}".format(users_dict[encrypt_utils.FROM_KEYWORD]))
                    self._log_message("to user ID: {}".format(users_dict[encrypt_utils.TO_KEYWORD]))
                    self._log_message("subject: {}".format(
                      self.crypto_message.get_email_message().get_header(mime_constants.SUBJECT_KEYWORD)))

                    result_ok = self._encrypt_message_with_keys(crypto, users_dict)
                    self._log_message('encrypted message: {}'.format(result_ok))
                    if result_ok:
                        self._log_message('encrypted with: {}'.format(encryption_name))
                    else:
                        error_message = self._get_encrypt_error_message(users_dict, encryption_name)
                        raise MessageException(value=error_message)

                else:
                    # the message hasn't been encrypted, but we have
                    # successfully processed it
                    self.crypto_message.set_filtered(True)

        except MessageException as message_exception:
            raise MessageException(value=message_exception.value)

        except Exception:
            result_ok = False
            record_exception()
            self._log_message('EXCEPTION - see syr.exception.log for details')

        return result_ok
    def encrypt_message(crypto_message, data):


        encryption_ready = False
        encrypted_with = []

        # use the metadata address' encryption
        to_metadata_address = metadata.get_metadata_address(email=to_user)
        encryption_names = contacts.get_encryption_names(to_metadata_address)
        log_message('{} encryption software for: {}'.format(encryption_names, to_metadata_address))

        if len(encryption_names) < 1:
            error_message = i18n(
              'Unable to protect metadata because there are no encryption programs for {}.'.format(to_metadata_address))
            log_message(error_message)
            raise MessageException(value=error_message)
        else:
            # encrypt with each common encryption program
            for encryption_name in encryption_names:
                ready, to_metadata_address, __ = metadata.get_metadata_user_details(
                    to_user, encryption_name)
                log_message('to metadata ready {} '.format(ready))

                if ready:
                    ready, from_metadata_address, passcode = metadata.get_from_metadata_user_details(
                        from_user, encryption_name)
                    log_message('metadata keys ready {}'.format(ready))

                if ready:
                    log_message('protecting metadata with {}'.format(encryption_names))

                    # if we're ready with any key, then the encryption is ready
                    encryption_ready = True

                    from_user_id = get_email(from_metadata_address)
                    to_user_id = get_email(to_metadata_address)
                    crypto_message.set_smtp_sender(from_user_id)
                    crypto_message.set_smtp_recipient(to_user_id)

                    # use the default charset to prevent metadata leakage
                    charset, __ = get_charset(constants.DEFAULT_CHAR_SET)
                    users_dict = {TO_KEYWORD: to_user_id,
                                  FROM_KEYWORD: from_user_id,
                                  PASSCODE_KEYWORD: passcode,
                                  CHARSET_KEYWORD: charset}

                    crypto = CryptoFactory.get_crypto(encryption_name, get_classname(encryption_name))
                    ciphertext, error_message = encrypt_byte_array(data, crypto, users_dict)
                    if ciphertext is not None and len(ciphertext) > 0:
                        crypto_message.get_email_message().get_message().set_payload(ciphertext)

                        crypto_message.add_public_key_to_header(users_dict[FROM_KEYWORD])
                        set_sigs(crypto_message, from_user_id, passcode)
                        crypto_message.set_filtered(True)
                        crypto_message.set_crypted(True)

                        # use the encrypted data for the next level of encryption
                        data = ciphertext

                        encrypted_with.append(encryption_name)
                    else:
                        log_message('unable to encrypt the metadata with {}'.format(encryption_name))
                        raise MessageException(value=error_message)
                else:
                    log_message('unable to protect metadata with {}'.format(encryption_name))

            return encryption_ready, encrypted_with