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()
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
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
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
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
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(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