-
Notifications
You must be signed in to change notification settings - Fork 3
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Does not send signed emails. #2
Comments
Are you specifying a true-ish value for |
Why does |
I have checked the code. It is not possible to send signed emails with this package, why was this even in the docs? Maybe this function was removed at some point and the docs were not updated? |
Sorry it's been awhile since I've touched this code. You're correct: I noted this in the documentation but it's really easy to overlook: this package uses the
This package absolutely does sign outgoing mail using the signing key specified by
Now, about how we use python-gnupg's
Circling back to your original assumption:
This is an incorrect assumption, although not necessarily a bad one. This package does not sign mail to recipients without encryption keys. This package does sign mail to recipients with encryption keys however. As to that: I'm not convinced that signing everything is really all that useful or necessary. Almost all mail nowadays is encrypted in transit, so a third party modifying mail in flight is pretty much no longer possible. You and your sender will both need to trust your SMTP gateway and the recipients' mail service to not modify the content of the email. You as the developer have a choice for who you pick as your SMTP provider, and to my knowledge none of the major ones have a reputation for modifying the content of mail in any meaningful way (eg: some add special/custom headers, but they can and do do that even if you sign and encrypt the content). You as the developer will not be able to predict or control the recipient's services, so that responsibility is really in their hands. And if they don't trust their provider to not modify their mail, they have probably already given you an encryption key. And even then, they still have to trust their mail service to not simply deny receiving mail. So no matter what, a recipient has to trust their mail service at some point. This means that the remaining use case for sending signed but unencrypted mail is really very small. Your SMTP provider and the recipients' mail service can still trivially strip the signature and modify the contents at will - most people don't check that mail is signed at all, much less check signatures of received mail, and those that do already know what digital signing is, expect mail to be encrypted, and very likely already have encryption keys they can use. So to me, the two main use cases are:
Use case # 1 probably already covers 99% of users, and both together probably cover 99.5%, so adding the third use case
doesn't really make sense to me, but I am still open to discussion, and I'm happy to answer any further questions you may have. Furthermore, your point about documentation is valid. At the very least, this should be documented. I was just laid off (while on vacation 😆), so I'll get to this in the next few days. I'll keep this issue open until I do. Thanks! |
@Euphorbium And since you seem to be interested in this project, if you see anything else that needs documentation or fixing up, don't hesitate to point it out! I'll have some time to devote to this later this week, so queue up anything you want me to do. |
Thanks for extensive reply. Also, about the trust. It is not about me trusting the smtp provider. Is about the receiver NOT having to trust anybody in between me as a sender, and him as a receiver. They don't have to inspect emails to see which provider sent the email, or know anything about that. What if my receiver runs their own service? There are use cases where this is necessary, and I need to send signed unencrypted emails. It increases the trust the receiver has in my project, since he does not have to waste his trust on the middle men. You can check my fork of this project, I've started work on |
What idiot documented this crap!? Oh right, it was me. Derp. 😆
My point was that they do have to trust your SMTP gateway and their mail service, no matter what. The recipient has to - at minimum - trust that your SMTP provider and their mail service is actually delivering mail. If either of those didn't deliver mail then the recipient wouldn't have any way of knowing, and the signature would be worthless. Furthermore, signing without encrypting is still trivially broken - your SMTP provider or the recipient's mail service can simply strip the signature off the message entirely, then modify the content at will. And the recipient will never know the difference. 1
Then they don't need signed messages to begin with - they simply use DKIM and SPF to verify that mail that claims to originate from you actually did originate from you. Done. Furthermore, if there is a non-negligible number of users running their own mail services I will be entirely surprised and impressed. Securely running mail servers is an subtly incredibly non-trivial task. About You have to think about how encryption failures should be handled - some sites will only encrypt mail to their admins (because sometimes mail contains sensitive information), but some sites may allow normal users to upload their PGP keys. PGP keys almost always expire, or they can be too short to be useful, or they can be malicious. The point is that encryption can fail for a multitude of reasons, and different sites will need to handle this failure in different ways. And it gets even more complicated than that - by default, Django will email the site admins when exceptions are raised. But what happens if an admin's encryption keys expires? When Django tries to mail the admin, this package will attempt to encrypt using their expired key, the encryption will fail, the default failure handlers will raise exceptions, so Django tries to email the admin, this package attempts to encrypt using the same expired key, which fails, etc., - an error loop happens. Sometimes sites will need to notify admins whether or not the message is encrypted, but maybe sometimes they don't want to because the message contents are too sensitive - they can simply log it. 2 Sites need flexibility in how to handle encryption failures, so that's why encryption failure handlers are user-configurable. The first part of this module is pretty boring - it's simply defining default handlers for when encryption fails. The default handlers are exceptionally boring (pun very much intended): they just re-raise the exception. def default_handle_failed_encryption(exception):
"""
Handle failures when trying to encrypt content for messages
"""
raise exception
def default_handle_failed_alternative_encryption(exception):
"""
Handle failures when trying to encrypt alternative content for messages
"""
raise exception
def default_handle_failed_attachment_encryption(exception):
"""
Handle failures when trying to encrypt attachment content for messages
"""
raise exception The "second" part is defining functions that I thought might be useful for users if they write their own failure handlers: def get_variable_from_exception(exception, variable_name):
... def force_mail_admins(unencrypted_message, address):
...
def force_delete_key(address):
...
def force_send_message(unencrypted_message):
... The third part is cool though: def import_function(key):
mod, _, function = FAILURE_HANDLERS[key].rpartition('.')
mod = import_module(mod)
return getattr(mod, function) That simply imports failure handling functions from their import path string. The path strings are the values in exception_handlers = {
'message': 'handle_failed_message_encryption',
'alternative': 'handle_failed_alternative_encryption',
'attachment': 'handle_failed_attachment_encryption',
}
for key, value in exception_handlers.items():
locals()[value] = import_function(key) This code dynamically sets the local variables This means that importing 1 Unless they expect all mail from you to be signed. But encryption and digital signatures are far from ubiquitous, so I think this is a rather weak argument. |
Every crypto service was and is plagued by email spoofing attacks. Experienced users expect emails to be signed by now. Add this line to your website and twitter: |
Yes, and SPF and DKIM largely prevent header/sender spoofing. Content spoofing is another thing entirely, and is only solved by encrypting the signed message - which is exactly what this package already does, not just by signing the unencrypted message. End to end encryption is good for making sure the content isn't read by anybody except the recipient, but it is also good for ensuring that the content isn't changed along the way. Signing is only useful for non-repudiation, which is different than spoofing, and only if the signature cannot be trivially stripped off the message. Simply signing without encrypting does not effectively prevent any malicious party from modifying or spoofing message content. Signing is not the silver bullet you seem to think it is.
This is unfortunately simply untrue. And even if it was true, I can just as easily turn this around on you: experienced users expect emails to be signed and encrypted by now.
How do users know to check Twitter? What if the Twitter account is hacked and that tagline is removed? How is Twitter more trustworthy than your recipient's mail service? If users want to ensure that the content of the email is not changed in flight, they can upload their public key. Bam, now all of their emails are signed and encrypted. Mail to them is now impossible to spoof or modify along the way. Security is really difficult to implement, and nearly impossible to implement well. This package aims to change that. But part of that is not allowing our users to do things that are trivial to work around. I refuse to add a backend that only signs emails, because it pretends to be secure when it really actually isn't. I have given you guidance on how to implement a signing fallback in the encrypting backend, and I might be interested in that pull request. But I do not want to make it easy for users to think they are secure when they really are not, and that's exactly what a signing-only backend does. |
Closing due to inactivity, but feel free to comment and/or ask me to reopen this issue if the backend altogether stops signing mail that should be signed and encrypted. And just to be completely clear: I will not merge in a signing-only backend, but I would accept a PR that implements a signing-only fallback in the case where encrypting mail fails. |
Sending encrypted mails work. I assume that all emails sent using
'secure_mail.backends.EncryptingSmtpEmailBackend'
should be signed, if the to key does not exist.The text was updated successfully, but these errors were encountered: